Skip to content

Commit e8a0464

Browse files
committed
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 <[email protected]>
1 parent 070825b commit e8a0464

File tree

18 files changed

+320
-137
lines changed

18 files changed

+320
-137
lines changed

drivers/net/bonding/bond_main.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5042,15 +5042,17 @@ static int bond_check_params(struct bond_params *params)
50425042

50435043
static struct lock_class_key bonding_netdev_xmit_lock_key;
50445044

5045-
static void bond_set_lockdep_class_one(struct netdev_queue *txq)
5045+
static void bond_set_lockdep_class_one(struct net_device *dev,
5046+
struct netdev_queue *txq,
5047+
void *_unused)
50465048
{
50475049
lockdep_set_class(&txq->_xmit_lock,
50485050
&bonding_netdev_xmit_lock_key);
50495051
}
50505052

50515053
static void bond_set_lockdep_class(struct net_device *dev)
50525054
{
5053-
bond_set_lockdep_class_one(&dev->tx_queue);
5055+
netdev_for_each_tx_queue(dev, bond_set_lockdep_class_one, NULL);
50545056
}
50555057

50565058
/* Create a new bond based on the specified name and bonding parameters.

drivers/net/hamradio/bpqether.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,14 +124,16 @@ static LIST_HEAD(bpq_devices);
124124
*/
125125
static struct lock_class_key bpq_netdev_xmit_lock_key;
126126

127-
static void bpq_set_lockdep_class_one(struct netdev_queue *txq)
127+
static void bpq_set_lockdep_class_one(struct net_device *dev,
128+
struct netdev_queue *txq,
129+
void *_unused)
128130
{
129131
lockdep_set_class(&txq->_xmit_lock, &bpq_netdev_xmit_lock_key);
130132
}
131133

132134
static void bpq_set_lockdep_class(struct net_device *dev)
133135
{
134-
bpq_set_lockdep_class_one(&dev->tx_queue);
136+
netdev_for_each_tx_queue(dev, bpq_set_lockdep_class_one, NULL);
135137
}
136138

137139
/* ------------------------------------------------------------------------ */

drivers/net/ifb.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -229,14 +229,20 @@ module_param(numifbs, int, 0);
229229
MODULE_PARM_DESC(numifbs, "Number of ifb devices");
230230

231231
/*
232-
* dev_ifb->tx_queue.lock is usually taken after dev->rx_queue.lock,
232+
* dev_ifb's TX queue lock is usually taken after dev->rx_queue.lock,
233233
* reversely to e.g. qdisc_lock_tree(). It should be safe until
234-
* ifb doesn't take dev->tx_queue.lock with dev_ifb->rx_queue.lock.
234+
* ifb doesn't take dev's TX queue lock with dev_ifb->rx_queue.lock.
235235
* But lockdep should know that ifb has different locks from dev.
236236
*/
237237
static struct lock_class_key ifb_tx_queue_lock_key;
238238
static struct lock_class_key ifb_rx_queue_lock_key;
239239

240+
static void set_tx_lockdep_key(struct net_device *dev,
241+
struct netdev_queue *txq,
242+
void *_unused)
243+
{
244+
lockdep_set_class(&txq->lock, &ifb_tx_queue_lock_key);
245+
}
240246

241247
static int __init ifb_init_one(int index)
242248
{
@@ -258,7 +264,7 @@ static int __init ifb_init_one(int index)
258264
if (err < 0)
259265
goto err;
260266

261-
lockdep_set_class(&dev_ifb->tx_queue.lock, &ifb_tx_queue_lock_key);
267+
netdev_for_each_tx_queue(dev_ifb, set_tx_lockdep_key, NULL);
262268
lockdep_set_class(&dev_ifb->rx_queue.lock, &ifb_rx_queue_lock_key);
263269

264270
return 0;

drivers/net/macvlan.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -285,15 +285,17 @@ static struct lock_class_key macvlan_netdev_xmit_lock_key;
285285
#define MACVLAN_STATE_MASK \
286286
((1<<__LINK_STATE_NOCARRIER) | (1<<__LINK_STATE_DORMANT))
287287

288-
static void macvlan_set_lockdep_class_one(struct netdev_queue *txq)
288+
static void macvlan_set_lockdep_class_one(struct net_device *dev,
289+
struct netdev_queue *txq,
290+
void *_unused)
289291
{
290292
lockdep_set_class(&txq->_xmit_lock,
291293
&macvlan_netdev_xmit_lock_key);
292294
}
293295

294296
static void macvlan_set_lockdep_class(struct net_device *dev)
295297
{
296-
macvlan_set_lockdep_class_one(&dev->tx_queue);
298+
netdev_for_each_tx_queue(dev, macvlan_set_lockdep_class_one, NULL);
297299
}
298300

299301
static int macvlan_init(struct net_device *dev)

drivers/net/wireless/hostap/hostap_hw.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3102,15 +3102,17 @@ static void prism2_clear_set_tim_queue(local_info_t *local)
31023102
*/
31033103
static struct lock_class_key hostap_netdev_xmit_lock_key;
31043104

3105-
static void prism2_set_lockdep_class_one(struct netdev_queue *txq)
3105+
static void prism2_set_lockdep_class_one(struct net_device *dev,
3106+
struct netdev_queue *txq,
3107+
void *_unused)
31063108
{
31073109
lockdep_set_class(&txq->_xmit_lock,
31083110
&hostap_netdev_xmit_lock_key);
31093111
}
31103112

31113113
static void prism2_set_lockdep_class(struct net_device *dev)
31123114
{
3113-
prism2_set_lockdep_class_one(&dev->tx_queue);
3115+
netdev_for_each_tx_queue(dev, prism2_set_lockdep_class_one, NULL);
31143116
}
31153117

31163118
static struct net_device *

include/linux/netdevice.h

Lines changed: 46 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -463,7 +463,7 @@ struct netdev_queue {
463463
struct Qdisc *qdisc_sleeping;
464464
struct list_head qdisc_list;
465465
struct netdev_queue *next_sched;
466-
};
466+
} ____cacheline_aligned_in_smp;
467467

468468
/*
469469
* The DEVICE structure.
@@ -641,7 +641,9 @@ struct net_device
641641
unsigned char broadcast[MAX_ADDR_LEN]; /* hw bcast add */
642642

643643
struct netdev_queue rx_queue;
644-
struct netdev_queue tx_queue ____cacheline_aligned_in_smp;
644+
645+
struct netdev_queue *_tx ____cacheline_aligned_in_smp;
646+
unsigned int num_tx_queues;
645647
unsigned long tx_queue_len; /* Max frames per queue allowed */
646648

647649
/*
@@ -764,6 +766,25 @@ struct net_device
764766
#define NETDEV_ALIGN 32
765767
#define NETDEV_ALIGN_CONST (NETDEV_ALIGN - 1)
766768

769+
static inline
770+
struct netdev_queue *netdev_get_tx_queue(const struct net_device *dev,
771+
unsigned int index)
772+
{
773+
return &dev->_tx[index];
774+
}
775+
776+
static inline void netdev_for_each_tx_queue(struct net_device *dev,
777+
void (*f)(struct net_device *,
778+
struct netdev_queue *,
779+
void *),
780+
void *arg)
781+
{
782+
unsigned int i;
783+
784+
for (i = 0; i < dev->num_tx_queues; i++)
785+
f(dev, &dev->_tx[i], arg);
786+
}
787+
767788
/*
768789
* Net namespace inlines
769790
*/
@@ -977,7 +998,7 @@ static inline void netif_schedule_queue(struct netdev_queue *txq)
977998

978999
static inline void netif_schedule(struct net_device *dev)
9791000
{
980-
netif_schedule_queue(&dev->tx_queue);
1001+
netif_schedule_queue(netdev_get_tx_queue(dev, 0));
9811002
}
9821003

9831004
/**
@@ -993,7 +1014,7 @@ static inline void netif_tx_start_queue(struct netdev_queue *dev_queue)
9931014

9941015
static inline void netif_start_queue(struct net_device *dev)
9951016
{
996-
netif_tx_start_queue(&dev->tx_queue);
1017+
netif_tx_start_queue(netdev_get_tx_queue(dev, 0));
9971018
}
9981019

9991020
/**
@@ -1017,7 +1038,7 @@ static inline void netif_tx_wake_queue(struct netdev_queue *dev_queue)
10171038

10181039
static inline void netif_wake_queue(struct net_device *dev)
10191040
{
1020-
netif_tx_wake_queue(&dev->tx_queue);
1041+
netif_tx_wake_queue(netdev_get_tx_queue(dev, 0));
10211042
}
10221043

10231044
/**
@@ -1034,7 +1055,7 @@ static inline void netif_tx_stop_queue(struct netdev_queue *dev_queue)
10341055

10351056
static inline void netif_stop_queue(struct net_device *dev)
10361057
{
1037-
netif_tx_stop_queue(&dev->tx_queue);
1058+
netif_tx_stop_queue(netdev_get_tx_queue(dev, 0));
10381059
}
10391060

10401061
/**
@@ -1050,7 +1071,7 @@ static inline int netif_tx_queue_stopped(const struct netdev_queue *dev_queue)
10501071

10511072
static inline int netif_queue_stopped(const struct net_device *dev)
10521073
{
1053-
return netif_tx_queue_stopped(&dev->tx_queue);
1074+
return netif_tx_queue_stopped(netdev_get_tx_queue(dev, 0));
10541075
}
10551076

10561077
/**
@@ -1134,7 +1155,7 @@ static inline void netif_wake_subqueue(struct net_device *dev, u16 queue_index)
11341155
#endif
11351156
if (test_and_clear_bit(__QUEUE_STATE_XOFF,
11361157
&dev->egress_subqueue[queue_index].state))
1137-
__netif_schedule(&dev->tx_queue);
1158+
__netif_schedule(netdev_get_tx_queue(dev, 0));
11381159
}
11391160

11401161
/**
@@ -1430,18 +1451,19 @@ static inline void __netif_tx_lock(struct netdev_queue *txq, int cpu)
14301451

14311452
static inline void netif_tx_lock(struct net_device *dev)
14321453
{
1433-
__netif_tx_lock(&dev->tx_queue, smp_processor_id());
1434-
}
1454+
int cpu = smp_processor_id();
1455+
unsigned int i;
14351456

1436-
static inline void __netif_tx_lock_bh(struct netdev_queue *txq)
1437-
{
1438-
spin_lock_bh(&txq->_xmit_lock);
1439-
txq->xmit_lock_owner = smp_processor_id();
1457+
for (i = 0; i < dev->num_tx_queues; i++) {
1458+
struct netdev_queue *txq = netdev_get_tx_queue(dev, i);
1459+
__netif_tx_lock(txq, cpu);
1460+
}
14401461
}
14411462

14421463
static inline void netif_tx_lock_bh(struct net_device *dev)
14431464
{
1444-
__netif_tx_lock_bh(&dev->tx_queue);
1465+
local_bh_disable();
1466+
netif_tx_lock(dev);
14451467
}
14461468

14471469
static inline int __netif_tx_trylock(struct netdev_queue *txq)
@@ -1454,7 +1476,7 @@ static inline int __netif_tx_trylock(struct netdev_queue *txq)
14541476

14551477
static inline int netif_tx_trylock(struct net_device *dev)
14561478
{
1457-
return __netif_tx_trylock(&dev->tx_queue);
1479+
return __netif_tx_trylock(netdev_get_tx_queue(dev, 0));
14581480
}
14591481

14601482
static inline void __netif_tx_unlock(struct netdev_queue *txq)
@@ -1465,18 +1487,19 @@ static inline void __netif_tx_unlock(struct netdev_queue *txq)
14651487

14661488
static inline void netif_tx_unlock(struct net_device *dev)
14671489
{
1468-
__netif_tx_unlock(&dev->tx_queue);
1469-
}
1490+
unsigned int i;
1491+
1492+
for (i = 0; i < dev->num_tx_queues; i++) {
1493+
struct netdev_queue *txq = netdev_get_tx_queue(dev, i);
1494+
__netif_tx_unlock(txq);
1495+
}
14701496

1471-
static inline void __netif_tx_unlock_bh(struct netdev_queue *txq)
1472-
{
1473-
txq->xmit_lock_owner = -1;
1474-
spin_unlock_bh(&txq->_xmit_lock);
14751497
}
14761498

14771499
static inline void netif_tx_unlock_bh(struct net_device *dev)
14781500
{
1479-
__netif_tx_unlock_bh(&dev->tx_queue);
1501+
netif_tx_unlock(dev);
1502+
local_bh_enable();
14801503
}
14811504

14821505
#define HARD_TX_LOCK(dev, txq, cpu) { \

include/net/sch_generic.h

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -230,32 +230,47 @@ extern void tcf_destroy_chain(struct tcf_proto **fl);
230230
/* Reset all TX qdiscs of a device. */
231231
static inline void qdisc_reset_all_tx(struct net_device *dev)
232232
{
233-
qdisc_reset(dev->tx_queue.qdisc);
233+
unsigned int i;
234+
for (i = 0; i < dev->num_tx_queues; i++)
235+
qdisc_reset(netdev_get_tx_queue(dev, i)->qdisc);
234236
}
235237

236238
/* Are all TX queues of the device empty? */
237239
static inline bool qdisc_all_tx_empty(const struct net_device *dev)
238240
{
239-
const struct netdev_queue *txq = &dev->tx_queue;
240-
const struct Qdisc *q = txq->qdisc;
241+
unsigned int i;
242+
for (i = 0; i < dev->num_tx_queues; i++) {
243+
struct netdev_queue *txq = netdev_get_tx_queue(dev, i);
244+
const struct Qdisc *q = txq->qdisc;
241245

242-
return (q->q.qlen == 0);
246+
if (q->q.qlen)
247+
return false;
248+
}
249+
return true;
243250
}
244251

245252
/* Are any of the TX qdiscs changing? */
246253
static inline bool qdisc_tx_changing(struct net_device *dev)
247254
{
248-
struct netdev_queue *txq = &dev->tx_queue;
249-
250-
return (txq->qdisc != txq->qdisc_sleeping);
255+
unsigned int i;
256+
for (i = 0; i < dev->num_tx_queues; i++) {
257+
struct netdev_queue *txq = netdev_get_tx_queue(dev, i);
258+
if (txq->qdisc != txq->qdisc_sleeping)
259+
return true;
260+
}
261+
return false;
251262
}
252263

253-
/* Is the device using the noop qdisc? */
264+
/* Is the device using the noop qdisc on all queues? */
254265
static inline bool qdisc_tx_is_noop(const struct net_device *dev)
255266
{
256-
const struct netdev_queue *txq = &dev->tx_queue;
257-
258-
return (txq->qdisc == &noop_qdisc);
267+
unsigned int i;
268+
for (i = 0; i < dev->num_tx_queues; i++) {
269+
struct netdev_queue *txq = netdev_get_tx_queue(dev, i);
270+
if (txq->qdisc != &noop_qdisc)
271+
return false;
272+
}
273+
return true;
259274
}
260275

261276
static inline int __qdisc_enqueue_tail(struct sk_buff *skb, struct Qdisc *sch,

net/8021q/vlan_dev.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -570,16 +570,18 @@ static void vlan_dev_set_rx_mode(struct net_device *vlan_dev)
570570
*/
571571
static struct lock_class_key vlan_netdev_xmit_lock_key;
572572

573-
static void vlan_dev_set_lockdep_one(struct netdev_queue *txq,
574-
int subclass)
573+
static void vlan_dev_set_lockdep_one(struct net_device *dev,
574+
struct netdev_queue *txq,
575+
void *_subclass)
575576
{
576577
lockdep_set_class_and_subclass(&txq->_xmit_lock,
577-
&vlan_netdev_xmit_lock_key, subclass);
578+
&vlan_netdev_xmit_lock_key,
579+
*(int *)_subclass);
578580
}
579581

580582
static void vlan_dev_set_lockdep_class(struct net_device *dev, int subclass)
581583
{
582-
vlan_dev_set_lockdep_one(&dev->tx_queue, subclass);
584+
netdev_for_each_tx_queue(dev, vlan_dev_set_lockdep_one, &subclass);
583585
}
584586

585587
static const struct header_ops vlan_header_ops = {

0 commit comments

Comments
 (0)