aboutsummaryrefslogtreecommitdiffstats
path: root/include/net/sch_generic.h
diff options
context:
space:
mode:
authorJohn Fastabend <john.fastabend@gmail.com>2014-09-12 23:04:52 -0400
committerDavid S. Miller <davem@davemloft.net>2014-09-13 12:30:25 -0400
commit46e5da40aec256155cfedee96dd21a75da941f2c (patch)
treecc3986c52025d252c2a063053692595e60c80e13 /include/net/sch_generic.h
parentd1015645dd535bbf10e52a3ef6d02ee0c3e0b267 (diff)
net: qdisc: use rcu prefix and silence sparse warnings
Add __rcu notation to qdisc handling by doing this we can make smatch output more legible. And anyways some of the cases should be using rcu_dereference() see qdisc_all_tx_empty(), qdisc_tx_chainging(), and so on. Also *wake_queue() API is commonly called from driver timer routines without rcu lock or rtnl lock. So I added rcu_read_lock() blocks around netif_wake_subqueue and netif_tx_wake_queue. Signed-off-by: John Fastabend <john.r.fastabend@intel.com> Acked-by: Eric Dumazet <edumazet@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include/net/sch_generic.h')
-rw-r--r--include/net/sch_generic.h21
1 files changed, 15 insertions, 6 deletions
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index a3cfb8ebeb53..56838ab29b42 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -259,7 +259,9 @@ static inline spinlock_t *qdisc_lock(struct Qdisc *qdisc)
259 259
260static inline struct Qdisc *qdisc_root(const struct Qdisc *qdisc) 260static inline struct Qdisc *qdisc_root(const struct Qdisc *qdisc)
261{ 261{
262 return qdisc->dev_queue->qdisc; 262 struct Qdisc *q = rcu_dereference_rtnl(qdisc->dev_queue->qdisc);
263
264 return q;
263} 265}
264 266
265static inline struct Qdisc *qdisc_root_sleeping(const struct Qdisc *qdisc) 267static inline struct Qdisc *qdisc_root_sleeping(const struct Qdisc *qdisc)
@@ -384,7 +386,7 @@ static inline void qdisc_reset_all_tx_gt(struct net_device *dev, unsigned int i)
384 struct Qdisc *qdisc; 386 struct Qdisc *qdisc;
385 387
386 for (; i < dev->num_tx_queues; i++) { 388 for (; i < dev->num_tx_queues; i++) {
387 qdisc = netdev_get_tx_queue(dev, i)->qdisc; 389 qdisc = rtnl_dereference(netdev_get_tx_queue(dev, i)->qdisc);
388 if (qdisc) { 390 if (qdisc) {
389 spin_lock_bh(qdisc_lock(qdisc)); 391 spin_lock_bh(qdisc_lock(qdisc));
390 qdisc_reset(qdisc); 392 qdisc_reset(qdisc);
@@ -402,13 +404,18 @@ static inline void qdisc_reset_all_tx(struct net_device *dev)
402static inline bool qdisc_all_tx_empty(const struct net_device *dev) 404static inline bool qdisc_all_tx_empty(const struct net_device *dev)
403{ 405{
404 unsigned int i; 406 unsigned int i;
407
408 rcu_read_lock();
405 for (i = 0; i < dev->num_tx_queues; i++) { 409 for (i = 0; i < dev->num_tx_queues; i++) {
406 struct netdev_queue *txq = netdev_get_tx_queue(dev, i); 410 struct netdev_queue *txq = netdev_get_tx_queue(dev, i);
407 const struct Qdisc *q = txq->qdisc; 411 const struct Qdisc *q = rcu_dereference(txq->qdisc);
408 412
409 if (q->q.qlen) 413 if (q->q.qlen) {
414 rcu_read_unlock();
410 return false; 415 return false;
416 }
411 } 417 }
418 rcu_read_unlock();
412 return true; 419 return true;
413} 420}
414 421
@@ -416,9 +423,10 @@ static inline bool qdisc_all_tx_empty(const struct net_device *dev)
416static inline bool qdisc_tx_changing(const struct net_device *dev) 423static inline bool qdisc_tx_changing(const struct net_device *dev)
417{ 424{
418 unsigned int i; 425 unsigned int i;
426
419 for (i = 0; i < dev->num_tx_queues; i++) { 427 for (i = 0; i < dev->num_tx_queues; i++) {
420 struct netdev_queue *txq = netdev_get_tx_queue(dev, i); 428 struct netdev_queue *txq = netdev_get_tx_queue(dev, i);
421 if (txq->qdisc != txq->qdisc_sleeping) 429 if (rcu_access_pointer(txq->qdisc) != txq->qdisc_sleeping)
422 return true; 430 return true;
423 } 431 }
424 return false; 432 return false;
@@ -428,9 +436,10 @@ static inline bool qdisc_tx_changing(const struct net_device *dev)
428static inline bool qdisc_tx_is_noop(const struct net_device *dev) 436static inline bool qdisc_tx_is_noop(const struct net_device *dev)
429{ 437{
430 unsigned int i; 438 unsigned int i;
439
431 for (i = 0; i < dev->num_tx_queues; i++) { 440 for (i = 0; i < dev->num_tx_queues; i++) {
432 struct netdev_queue *txq = netdev_get_tx_queue(dev, i); 441 struct netdev_queue *txq = netdev_get_tx_queue(dev, i);
433 if (txq->qdisc != &noop_qdisc) 442 if (rcu_access_pointer(txq->qdisc) != &noop_qdisc)
434 return false; 443 return false;
435 } 444 }
436 return true; 445 return true;