sch_mqprio.c (e4655e4a79133503ceec1dcd2f92734293b25610) | sch_mqprio.c (32302902ff093891d8e64439cbb8ceae83e21ef8) |
---|---|
1/* 2 * net/sched/sch_mqprio.c 3 * 4 * Copyright (c) 2010 John Fastabend <john.r.fastabend@intel.com> 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License 8 * version 2 as published by the Free Software Foundation. --- 139 unchanged lines hidden (view full) --- 148 BUILD_BUG_ON(TC_BITMASK != TC_QOPT_BITMASK); 149 150 if (sch->parent != TC_H_ROOT) 151 return -EOPNOTSUPP; 152 153 if (!netif_is_multiqueue(dev)) 154 return -EOPNOTSUPP; 155 | 1/* 2 * net/sched/sch_mqprio.c 3 * 4 * Copyright (c) 2010 John Fastabend <john.r.fastabend@intel.com> 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License 8 * version 2 as published by the Free Software Foundation. --- 139 unchanged lines hidden (view full) --- 148 BUILD_BUG_ON(TC_BITMASK != TC_QOPT_BITMASK); 149 150 if (sch->parent != TC_H_ROOT) 151 return -EOPNOTSUPP; 152 153 if (!netif_is_multiqueue(dev)) 154 return -EOPNOTSUPP; 155 |
156 /* make certain can allocate enough classids to handle queues */ 157 if (dev->num_tx_queues >= TC_H_MIN_PRIORITY) 158 return -ENOMEM; 159 |
|
156 if (!opt || nla_len(opt) < sizeof(*qopt)) 157 return -EINVAL; 158 159 qopt = nla_data(opt); 160 if (mqprio_parse_opt(dev, qopt)) 161 return -EINVAL; 162 163 if (len > 0) { --- 136 unchanged lines hidden (view full) --- 300 kfree(priv->qdiscs); 301 priv->qdiscs = NULL; 302} 303 304static struct netdev_queue *mqprio_queue_get(struct Qdisc *sch, 305 unsigned long cl) 306{ 307 struct net_device *dev = qdisc_dev(sch); | 160 if (!opt || nla_len(opt) < sizeof(*qopt)) 161 return -EINVAL; 162 163 qopt = nla_data(opt); 164 if (mqprio_parse_opt(dev, qopt)) 165 return -EINVAL; 166 167 if (len > 0) { --- 136 unchanged lines hidden (view full) --- 304 kfree(priv->qdiscs); 305 priv->qdiscs = NULL; 306} 307 308static struct netdev_queue *mqprio_queue_get(struct Qdisc *sch, 309 unsigned long cl) 310{ 311 struct net_device *dev = qdisc_dev(sch); |
308 unsigned long ntx = cl - 1 - netdev_get_num_tc(dev); | 312 unsigned long ntx = cl - 1; |
309 310 if (ntx >= dev->num_tx_queues) 311 return NULL; 312 return netdev_get_tx_queue(dev, ntx); 313} 314 315static int mqprio_graft(struct Qdisc *sch, unsigned long cl, struct Qdisc *new, 316 struct Qdisc **old) --- 125 unchanged lines hidden (view full) --- 442 return dev_queue->qdisc_sleeping; 443} 444 445static unsigned long mqprio_find(struct Qdisc *sch, u32 classid) 446{ 447 struct net_device *dev = qdisc_dev(sch); 448 unsigned int ntx = TC_H_MIN(classid); 449 | 313 314 if (ntx >= dev->num_tx_queues) 315 return NULL; 316 return netdev_get_tx_queue(dev, ntx); 317} 318 319static int mqprio_graft(struct Qdisc *sch, unsigned long cl, struct Qdisc *new, 320 struct Qdisc **old) --- 125 unchanged lines hidden (view full) --- 446 return dev_queue->qdisc_sleeping; 447} 448 449static unsigned long mqprio_find(struct Qdisc *sch, u32 classid) 450{ 451 struct net_device *dev = qdisc_dev(sch); 452 unsigned int ntx = TC_H_MIN(classid); 453 |
450 if (ntx > dev->num_tx_queues + netdev_get_num_tc(dev)) 451 return 0; 452 return ntx; | 454 /* There are essentially two regions here that have valid classid 455 * values. The first region will have a classid value of 1 through 456 * num_tx_queues. All of these are backed by actual Qdiscs. 457 */ 458 if (ntx < TC_H_MIN_PRIORITY) 459 return (ntx <= dev->num_tx_queues) ? ntx : 0; 460 461 /* The second region represents the hardware traffic classes. These 462 * are represented by classid values of TC_H_MIN_PRIORITY through 463 * TC_H_MIN_PRIORITY + netdev_get_num_tc - 1 464 */ 465 return ((ntx - TC_H_MIN_PRIORITY) < netdev_get_num_tc(dev)) ? ntx : 0; |
453} 454 455static int mqprio_dump_class(struct Qdisc *sch, unsigned long cl, 456 struct sk_buff *skb, struct tcmsg *tcm) 457{ | 466} 467 468static int mqprio_dump_class(struct Qdisc *sch, unsigned long cl, 469 struct sk_buff *skb, struct tcmsg *tcm) 470{ |
458 struct net_device *dev = qdisc_dev(sch); | 471 if (cl < TC_H_MIN_PRIORITY) { 472 struct netdev_queue *dev_queue = mqprio_queue_get(sch, cl); 473 struct net_device *dev = qdisc_dev(sch); 474 int tc = netdev_txq_to_tc(dev, cl - 1); |
459 | 475 |
460 if (cl <= netdev_get_num_tc(dev)) { | 476 tcm->tcm_parent = (tc < 0) ? 0 : 477 TC_H_MAKE(TC_H_MAJ(sch->handle), 478 TC_H_MIN(tc + TC_H_MIN_PRIORITY)); 479 tcm->tcm_info = dev_queue->qdisc_sleeping->handle; 480 } else { |
461 tcm->tcm_parent = TC_H_ROOT; 462 tcm->tcm_info = 0; | 481 tcm->tcm_parent = TC_H_ROOT; 482 tcm->tcm_info = 0; |
463 } else { 464 int i; 465 struct netdev_queue *dev_queue; 466 467 dev_queue = mqprio_queue_get(sch, cl); 468 tcm->tcm_parent = 0; 469 for (i = 0; i < netdev_get_num_tc(dev); i++) { 470 struct netdev_tc_txq tc = dev->tc_to_txq[i]; 471 int q_idx = cl - netdev_get_num_tc(dev); 472 473 if (q_idx > tc.offset && 474 q_idx <= tc.offset + tc.count) { 475 tcm->tcm_parent = 476 TC_H_MAKE(TC_H_MAJ(sch->handle), 477 TC_H_MIN(i + 1)); 478 break; 479 } 480 } 481 tcm->tcm_info = dev_queue->qdisc_sleeping->handle; | |
482 } 483 tcm->tcm_handle |= TC_H_MIN(cl); 484 return 0; 485} 486 487static int mqprio_dump_class_stats(struct Qdisc *sch, unsigned long cl, 488 struct gnet_dump *d) 489 __releases(d->lock) 490 __acquires(d->lock) 491{ | 483 } 484 tcm->tcm_handle |= TC_H_MIN(cl); 485 return 0; 486} 487 488static int mqprio_dump_class_stats(struct Qdisc *sch, unsigned long cl, 489 struct gnet_dump *d) 490 __releases(d->lock) 491 __acquires(d->lock) 492{ |
492 struct net_device *dev = qdisc_dev(sch); 493 494 if (cl <= netdev_get_num_tc(dev)) { | 493 if (cl >= TC_H_MIN_PRIORITY) { |
495 int i; 496 __u32 qlen = 0; 497 struct Qdisc *qdisc; 498 struct gnet_stats_queue qstats = {0}; 499 struct gnet_stats_basic_packed bstats = {0}; | 494 int i; 495 __u32 qlen = 0; 496 struct Qdisc *qdisc; 497 struct gnet_stats_queue qstats = {0}; 498 struct gnet_stats_basic_packed bstats = {0}; |
500 struct netdev_tc_txq tc = dev->tc_to_txq[cl - 1]; | 499 struct net_device *dev = qdisc_dev(sch); 500 struct netdev_tc_txq tc = dev->tc_to_txq[cl & TC_BITMASK]; |
501 502 /* Drop lock here it will be reclaimed before touching 503 * statistics this is required because the d->lock we 504 * hold here is the look on dev_queue->qdisc_sleeping 505 * also acquired below. 506 */ 507 if (d->lock) 508 spin_unlock_bh(d->lock); --- 36 unchanged lines hidden (view full) --- 545 struct net_device *dev = qdisc_dev(sch); 546 unsigned long ntx; 547 548 if (arg->stop) 549 return; 550 551 /* Walk hierarchy with a virtual class per tc */ 552 arg->count = arg->skip; | 501 502 /* Drop lock here it will be reclaimed before touching 503 * statistics this is required because the d->lock we 504 * hold here is the look on dev_queue->qdisc_sleeping 505 * also acquired below. 506 */ 507 if (d->lock) 508 spin_unlock_bh(d->lock); --- 36 unchanged lines hidden (view full) --- 545 struct net_device *dev = qdisc_dev(sch); 546 unsigned long ntx; 547 548 if (arg->stop) 549 return; 550 551 /* Walk hierarchy with a virtual class per tc */ 552 arg->count = arg->skip; |
553 for (ntx = arg->skip; 554 ntx < dev->num_tx_queues + netdev_get_num_tc(dev); 555 ntx++) { | 553 for (ntx = arg->skip; ntx < netdev_get_num_tc(dev); ntx++) { 554 if (arg->fn(sch, ntx + TC_H_MIN_PRIORITY, arg) < 0) { 555 arg->stop = 1; 556 return; 557 } 558 arg->count++; 559 } 560 561 /* Pad the values and skip over unused traffic classes */ 562 if (ntx < TC_MAX_QUEUE) { 563 arg->count = TC_MAX_QUEUE; 564 ntx = TC_MAX_QUEUE; 565 } 566 567 /* Reset offset, sort out remaining per-queue qdiscs */ 568 for (ntx -= TC_MAX_QUEUE; ntx < dev->num_tx_queues; ntx++) { |
556 if (arg->fn(sch, ntx + 1, arg) < 0) { 557 arg->stop = 1; | 569 if (arg->fn(sch, ntx + 1, arg) < 0) { 570 arg->stop = 1; |
558 break; | 571 return; |
559 } 560 arg->count++; 561 } 562} 563 564static const struct Qdisc_class_ops mqprio_class_ops = { 565 .graft = mqprio_graft, 566 .leaf = mqprio_leaf, --- 31 unchanged lines hidden --- | 572 } 573 arg->count++; 574 } 575} 576 577static const struct Qdisc_class_ops mqprio_class_ops = { 578 .graft = mqprio_graft, 579 .leaf = mqprio_leaf, --- 31 unchanged lines hidden --- |