From patchwork Fri Sep 19 14:44:50 2008 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [take2] pkt_sched: Fix TX state checking in qdisc_run() Date: Fri, 19 Sep 2008 04:44:50 -0000 From: Jarek Poplawski X-Patchwork-Id: 629 Message-Id: <20080919144450.GA2646@ami.dom.local> To: David Miller Cc: Alexander Duyck , Alexander Duyck , netdev@vger.kernel.org, herbert@gondor.apana.org.au, kaber@trash.net Alas this time the changelog needs more details. Sorry, Jarek P. -----------------> (take 2) pkt_sched: Fix TX state checking in qdisc_run() Current check wrongly uses the state of the first tx queue for all tx queues in case of non-default qdiscs. This patch brings back per dev __LINK_STATE_XOFF flag, which is set when all tx queues are stopped. This check is needed in qdisc_run() to avoid useless __netif_schedule() calls. The wrongness of this check was first noticed by Herbert Xu. Signed-off-by: Jarek Poplawski diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 488c56e..dc76e4b 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -271,6 +271,7 @@ struct header_ops { enum netdev_state_t { + __LINK_STATE_XOFF, __LINK_STATE_START, __LINK_STATE_PRESENT, __LINK_STATE_NOCARRIER, @@ -1043,6 +1044,7 @@ static inline void netif_tx_wake_queue(struct netdev_queue *dev_queue) static inline void netif_wake_queue(struct net_device *dev) { netif_tx_wake_queue(netdev_get_tx_queue(dev, 0)); + clear_bit(__LINK_STATE_XOFF, &dev->state); } static inline void netif_tx_wake_all_queues(struct net_device *dev) @@ -1053,6 +1055,7 @@ static inline void netif_tx_wake_all_queues(struct net_device *dev) struct netdev_queue *txq = netdev_get_tx_queue(dev, i); netif_tx_wake_queue(txq); } + clear_bit(__LINK_STATE_XOFF, &dev->state); } static inline void netif_tx_stop_queue(struct netdev_queue *dev_queue) @@ -1069,6 +1072,7 @@ static inline void netif_tx_stop_queue(struct netdev_queue *dev_queue) */ static inline void netif_stop_queue(struct net_device *dev) { + set_bit(__LINK_STATE_XOFF, &dev->state); netif_tx_stop_queue(netdev_get_tx_queue(dev, 0)); } @@ -1076,6 +1080,7 @@ static inline void netif_tx_stop_all_queues(struct net_device *dev) { unsigned int i; + set_bit(__LINK_STATE_XOFF, &dev->state); for (i = 0; i < dev->num_tx_queues; i++) { struct netdev_queue *txq = netdev_get_tx_queue(dev, i); netif_tx_stop_queue(txq); @@ -1095,7 +1100,7 @@ static inline int netif_tx_queue_stopped(const struct netdev_queue *dev_queue) */ static inline int netif_queue_stopped(const struct net_device *dev) { - return netif_tx_queue_stopped(netdev_get_tx_queue(dev, 0)); + return test_bit(__LINK_STATE_XOFF, &dev->state); } static inline int netif_tx_queue_frozen(const struct netdev_queue *dev_queue) diff --git a/include/net/pkt_sched.h b/include/net/pkt_sched.h index b786a5b..1718a60 100644 --- a/include/net/pkt_sched.h +++ b/include/net/pkt_sched.h @@ -90,9 +90,7 @@ extern void __qdisc_run(struct Qdisc *q); static inline void qdisc_run(struct Qdisc *q) { - struct netdev_queue *txq = q->dev_queue; - - if (!netif_tx_queue_stopped(txq) && + if (!netif_queue_stopped(qdisc_dev(q)) && !test_and_set_bit(__QDISC_STATE_RUNNING, &q->state)) __qdisc_run(q); }