summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2008-07-17 00:34:19 -0700
committerDavid S. Miller <davem@davemloft.net>2008-07-17 19:21:00 -0700
commite8a0464cc950972824e2e128028ae3db666ec1ed (patch)
tree5022b95396c0f3b313531bc39b19543c03551b9a /include
parent070825b3840a743e21ebcc44f8279708a4fed977 (diff)
netdev: Allocate multiple queues for TX.
alloc_netdev_mq() now allocates an array of netdev_queue structures for TX, based upon the queue_count argument. Furthermore, all accesses to the TX queues are now vectored through the netdev_get_tx_queue() and netdev_for_each_tx_queue() interfaces. This makes it easy to grep the tree for all things that want to get to a TX queue of a net device. Problem spots which are not really multiqueue aware yet, and only work with one queue, can easily be spotted by grepping for all netdev_get_tx_queue() calls that pass in a zero index. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include')
-rw-r--r--include/linux/netdevice.h69
-rw-r--r--include/net/sch_generic.h37
2 files changed, 72 insertions, 34 deletions
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 570cf7affa72..f25d4f5a31b0 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -463,7 +463,7 @@ struct netdev_queue {
struct Qdisc *qdisc_sleeping;
struct list_head qdisc_list;
struct netdev_queue *next_sched;
-};
+} ____cacheline_aligned_in_smp;
/*
* The DEVICE structure.
@@ -641,7 +641,9 @@ struct net_device
unsigned char broadcast[MAX_ADDR_LEN]; /* hw bcast add */
struct netdev_queue rx_queue;
- struct netdev_queue tx_queue ____cacheline_aligned_in_smp;
+
+ struct netdev_queue *_tx ____cacheline_aligned_in_smp;
+ unsigned int num_tx_queues;
unsigned long tx_queue_len; /* Max frames per queue allowed */
/*
@@ -764,6 +766,25 @@ struct net_device
#define NETDEV_ALIGN 32
#define NETDEV_ALIGN_CONST (NETDEV_ALIGN - 1)
+static inline
+struct netdev_queue *netdev_get_tx_queue(const struct net_device *dev,
+ unsigned int index)
+{
+ return &dev->_tx[index];
+}
+
+static inline void netdev_for_each_tx_queue(struct net_device *dev,
+ void (*f)(struct net_device *,
+ struct netdev_queue *,
+ void *),
+ void *arg)
+{
+ unsigned int i;
+
+ for (i = 0; i < dev->num_tx_queues; i++)
+ f(dev, &dev->_tx[i], arg);
+}
+
/*
* Net namespace inlines
*/
@@ -977,7 +998,7 @@ static inline void netif_schedule_queue(struct netdev_queue *txq)
static inline void netif_schedule(struct net_device *dev)
{
- netif_schedule_queue(&dev->tx_queue);
+ netif_schedule_queue(netdev_get_tx_queue(dev, 0));
}
/**
@@ -993,7 +1014,7 @@ static inline void netif_tx_start_queue(struct netdev_queue *dev_queue)
static inline void netif_start_queue(struct net_device *dev)
{
- netif_tx_start_queue(&dev->tx_queue);
+ netif_tx_start_queue(netdev_get_tx_queue(dev, 0));
}
/**
@@ -1017,7 +1038,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(&dev->tx_queue);
+ netif_tx_wake_queue(netdev_get_tx_queue(dev, 0));
}
/**
@@ -1034,7 +1055,7 @@ static inline void netif_tx_stop_queue(struct netdev_queue *dev_queue)
static inline void netif_stop_queue(struct net_device *dev)
{
- netif_tx_stop_queue(&dev->tx_queue);
+ netif_tx_stop_queue(netdev_get_tx_queue(dev, 0));
}
/**
@@ -1050,7 +1071,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(&dev->tx_queue);
+ return netif_tx_queue_stopped(netdev_get_tx_queue(dev, 0));
}
/**
@@ -1134,7 +1155,7 @@ static inline void netif_wake_subqueue(struct net_device *dev, u16 queue_index)
#endif
if (test_and_clear_bit(__QUEUE_STATE_XOFF,
&dev->egress_subqueue[queue_index].state))
- __netif_schedule(&dev->tx_queue);
+ __netif_schedule(netdev_get_tx_queue(dev, 0));
}
/**
@@ -1430,18 +1451,19 @@ static inline void __netif_tx_lock(struct netdev_queue *txq, int cpu)
static inline void netif_tx_lock(struct net_device *dev)
{
- __netif_tx_lock(&dev->tx_queue, smp_processor_id());
-}
+ int cpu = smp_processor_id();
+ unsigned int i;
-static inline void __netif_tx_lock_bh(struct netdev_queue *txq)
-{
- spin_lock_bh(&txq->_xmit_lock);
- txq->xmit_lock_owner = smp_processor_id();
+ for (i = 0; i < dev->num_tx_queues; i++) {
+ struct netdev_queue *txq = netdev_get_tx_queue(dev, i);
+ __netif_tx_lock(txq, cpu);
+ }
}
static inline void netif_tx_lock_bh(struct net_device *dev)
{
- __netif_tx_lock_bh(&dev->tx_queue);
+ local_bh_disable();
+ netif_tx_lock(dev);
}
static inline int __netif_tx_trylock(struct netdev_queue *txq)
@@ -1454,7 +1476,7 @@ static inline int __netif_tx_trylock(struct netdev_queue *txq)
static inline int netif_tx_trylock(struct net_device *dev)
{
- return __netif_tx_trylock(&dev->tx_queue);
+ return __netif_tx_trylock(netdev_get_tx_queue(dev, 0));
}
static inline void __netif_tx_unlock(struct netdev_queue *txq)
@@ -1465,18 +1487,19 @@ static inline void __netif_tx_unlock(struct netdev_queue *txq)
static inline void netif_tx_unlock(struct net_device *dev)
{
- __netif_tx_unlock(&dev->tx_queue);
-}
+ unsigned int i;
+
+ for (i = 0; i < dev->num_tx_queues; i++) {
+ struct netdev_queue *txq = netdev_get_tx_queue(dev, i);
+ __netif_tx_unlock(txq);
+ }
-static inline void __netif_tx_unlock_bh(struct netdev_queue *txq)
-{
- txq->xmit_lock_owner = -1;
- spin_unlock_bh(&txq->_xmit_lock);
}
static inline void netif_tx_unlock_bh(struct net_device *dev)
{
- __netif_tx_unlock_bh(&dev->tx_queue);
+ netif_tx_unlock(dev);
+ local_bh_enable();
}
#define HARD_TX_LOCK(dev, txq, cpu) { \
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index 5ba66b555578..b47f556c66f8 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -230,32 +230,47 @@ extern void tcf_destroy_chain(struct tcf_proto **fl);
/* Reset all TX qdiscs of a device. */
static inline void qdisc_reset_all_tx(struct net_device *dev)
{
- qdisc_reset(dev->tx_queue.qdisc);
+ unsigned int i;
+ for (i = 0; i < dev->num_tx_queues; i++)
+ qdisc_reset(netdev_get_tx_queue(dev, i)->qdisc);
}
/* Are all TX queues of the device empty? */
static inline bool qdisc_all_tx_empty(const struct net_device *dev)
{
- const struct netdev_queue *txq = &dev->tx_queue;
- const struct Qdisc *q = txq->qdisc;
+ unsigned int i;
+ for (i = 0; i < dev->num_tx_queues; i++) {
+ struct netdev_queue *txq = netdev_get_tx_queue(dev, i);
+ const struct Qdisc *q = txq->qdisc;
- return (q->q.qlen == 0);
+ if (q->q.qlen)
+ return false;
+ }
+ return true;
}
/* Are any of the TX qdiscs changing? */
static inline bool qdisc_tx_changing(struct net_device *dev)
{
- struct netdev_queue *txq = &dev->tx_queue;
-
- return (txq->qdisc != txq->qdisc_sleeping);
+ unsigned int i;
+ for (i = 0; i < dev->num_tx_queues; i++) {
+ struct netdev_queue *txq = netdev_get_tx_queue(dev, i);
+ if (txq->qdisc != txq->qdisc_sleeping)
+ return true;
+ }
+ return false;
}
-/* Is the device using the noop qdisc? */
+/* Is the device using the noop qdisc on all queues? */
static inline bool qdisc_tx_is_noop(const struct net_device *dev)
{
- const struct netdev_queue *txq = &dev->tx_queue;
-
- return (txq->qdisc == &noop_qdisc);
+ unsigned int i;
+ for (i = 0; i < dev->num_tx_queues; i++) {
+ struct netdev_queue *txq = netdev_get_tx_queue(dev, i);
+ if (txq->qdisc != &noop_qdisc)
+ return false;
+ }
+ return true;
}
static inline int __qdisc_enqueue_tail(struct sk_buff *skb, struct Qdisc *sch,