Skip to content

Commit f0c6556

Browse files
committed
Merge branch 'sunvnet-multi-tx-queue'
Sowmini Varadhan says: ==================== sunvnet: Use multiple Tx queues. v2: moved tcp fix out of this series per David Miller feedback The primary objective of this patch-set is to address the suggestion from http://marc.info/?l=linux-netdev&m=140790778931563&w=2 With the changes in Patch 2, every vnet_port will get packets from a single tx-queue, and flow-control/head-of-line-blocking is confined to the vnet_ports that share that tx queue (as opposed to flow-controlling *all* peers). Patch 1 is an optimization that resets the DATA_READY bit when we re-enable Rx interrupts. This optimization lets us exit quickly from vnet_event_napi() when new data has not triggered an interrupt. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
2 parents cd21453 + d51bffd commit f0c6556

File tree

2 files changed

+66
-31
lines changed

2 files changed

+66
-31
lines changed

drivers/net/ethernet/sun/sunvnet.c

Lines changed: 64 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ MODULE_DESCRIPTION("Sun LDOM virtual network driver");
4040
MODULE_LICENSE("GPL");
4141
MODULE_VERSION(DRV_MODULE_VERSION);
4242

43+
#define VNET_MAX_TXQS 16
44+
4345
/* Heuristic for the number of times to exponentially backoff and
4446
* retry sending an LDC trigger when EAGAIN is encountered
4547
*/
@@ -551,6 +553,8 @@ static int vnet_ack(struct vnet_port *port, void *msgbuf)
551553
struct vnet *vp;
552554
u32 end;
553555
struct vio_net_desc *desc;
556+
struct netdev_queue *txq;
557+
554558
if (unlikely(pkt->tag.stype_env != VIO_DRING_DATA))
555559
return 0;
556560

@@ -580,7 +584,8 @@ static int vnet_ack(struct vnet_port *port, void *msgbuf)
580584
}
581585
netif_tx_unlock(dev);
582586

583-
if (unlikely(netif_queue_stopped(dev) &&
587+
txq = netdev_get_tx_queue(dev, port->q_index);
588+
if (unlikely(netif_tx_queue_stopped(txq) &&
584589
vnet_tx_dring_avail(dr) >= VNET_TX_WAKEUP_THRESH(dr)))
585590
return 1;
586591

@@ -608,31 +613,23 @@ static int handle_mcast(struct vnet_port *port, void *msgbuf)
608613
return 0;
609614
}
610615

611-
static void maybe_tx_wakeup(struct vnet *vp)
616+
/* Got back a STOPPED LDC message on port. If the queue is stopped,
617+
* wake it up so that we'll send out another START message at the
618+
* next TX.
619+
*/
620+
static void maybe_tx_wakeup(struct vnet_port *port)
612621
{
613-
struct net_device *dev = vp->dev;
622+
struct netdev_queue *txq;
614623

615-
netif_tx_lock(dev);
616-
if (likely(netif_queue_stopped(dev))) {
617-
struct vnet_port *port;
618-
int wake = 1;
619-
620-
rcu_read_lock();
621-
list_for_each_entry_rcu(port, &vp->port_list, list) {
622-
struct vio_dring_state *dr;
623-
624-
dr = &port->vio.drings[VIO_DRIVER_TX_RING];
625-
if (vnet_tx_dring_avail(dr) <
626-
VNET_TX_WAKEUP_THRESH(dr)) {
627-
wake = 0;
628-
break;
629-
}
630-
}
631-
rcu_read_unlock();
632-
if (wake)
633-
netif_wake_queue(dev);
624+
txq = netdev_get_tx_queue(port->vp->dev, port->q_index);
625+
__netif_tx_lock(txq, smp_processor_id());
626+
if (likely(netif_tx_queue_stopped(txq))) {
627+
struct vio_dring_state *dr;
628+
629+
dr = &port->vio.drings[VIO_DRIVER_TX_RING];
630+
netif_tx_wake_queue(txq);
634631
}
635-
netif_tx_unlock(dev);
632+
__netif_tx_unlock(txq);
636633
}
637634

638635
static inline bool port_is_up(struct vnet_port *vnet)
@@ -748,7 +745,7 @@ static int vnet_event_napi(struct vnet_port *port, int budget)
748745
break;
749746
}
750747
if (unlikely(tx_wakeup && err != -ECONNRESET))
751-
maybe_tx_wakeup(port->vp);
748+
maybe_tx_wakeup(port);
752749
return npkts;
753750
}
754751

@@ -760,6 +757,7 @@ static int vnet_poll(struct napi_struct *napi, int budget)
760757

761758
if (processed < budget) {
762759
napi_complete(napi);
760+
port->rx_event &= ~LDC_EVENT_DATA_READY;
763761
vio_set_intr(vio->vdev->rx_ino, HV_INTR_ENABLED);
764762
}
765763
return processed;
@@ -952,6 +950,16 @@ static inline struct sk_buff *vnet_skb_shape(struct sk_buff *skb, void **pstart,
952950
return skb;
953951
}
954952

953+
static u16
954+
vnet_select_queue(struct net_device *dev, struct sk_buff *skb,
955+
void *accel_priv, select_queue_fallback_t fallback)
956+
{
957+
struct vnet *vp = netdev_priv(dev);
958+
struct vnet_port *port = __tx_port_find(vp, skb);
959+
960+
return port->q_index;
961+
}
962+
955963
static int vnet_start_xmit(struct sk_buff *skb, struct net_device *dev)
956964
{
957965
struct vnet *vp = netdev_priv(dev);
@@ -964,6 +972,7 @@ static int vnet_start_xmit(struct sk_buff *skb, struct net_device *dev)
964972
void *start = NULL;
965973
int nlen = 0;
966974
unsigned pending = 0;
975+
struct netdev_queue *txq;
967976

968977
skb = vnet_skb_shape(skb, &start, &nlen);
969978
if (unlikely(!skb))
@@ -1007,9 +1016,11 @@ static int vnet_start_xmit(struct sk_buff *skb, struct net_device *dev)
10071016
}
10081017

10091018
dr = &port->vio.drings[VIO_DRIVER_TX_RING];
1019+
i = skb_get_queue_mapping(skb);
1020+
txq = netdev_get_tx_queue(dev, i);
10101021
if (unlikely(vnet_tx_dring_avail(dr) < 1)) {
1011-
if (!netif_queue_stopped(dev)) {
1012-
netif_stop_queue(dev);
1022+
if (!netif_tx_queue_stopped(txq)) {
1023+
netif_tx_stop_queue(txq);
10131024

10141025
/* This is a hard error, log it. */
10151026
netdev_err(dev, "BUG! Tx Ring full when queue awake!\n");
@@ -1103,9 +1114,9 @@ static int vnet_start_xmit(struct sk_buff *skb, struct net_device *dev)
11031114

11041115
dr->prod = (dr->prod + 1) & (VNET_TX_RING_SIZE - 1);
11051116
if (unlikely(vnet_tx_dring_avail(dr) < 1)) {
1106-
netif_stop_queue(dev);
1117+
netif_tx_stop_queue(txq);
11071118
if (vnet_tx_dring_avail(dr) > VNET_TX_WAKEUP_THRESH(dr))
1108-
netif_wake_queue(dev);
1119+
netif_tx_wake_queue(txq);
11091120
}
11101121

11111122
(void)mod_timer(&port->clean_timer, jiffies + VNET_CLEAN_TIMEOUT);
@@ -1138,14 +1149,14 @@ static void vnet_tx_timeout(struct net_device *dev)
11381149
static int vnet_open(struct net_device *dev)
11391150
{
11401151
netif_carrier_on(dev);
1141-
netif_start_queue(dev);
1152+
netif_tx_start_all_queues(dev);
11421153

11431154
return 0;
11441155
}
11451156

11461157
static int vnet_close(struct net_device *dev)
11471158
{
1148-
netif_stop_queue(dev);
1159+
netif_tx_stop_all_queues(dev);
11491160
netif_carrier_off(dev);
11501161

11511162
return 0;
@@ -1419,6 +1430,7 @@ static const struct net_device_ops vnet_ops = {
14191430
.ndo_tx_timeout = vnet_tx_timeout,
14201431
.ndo_change_mtu = vnet_change_mtu,
14211432
.ndo_start_xmit = vnet_start_xmit,
1433+
.ndo_select_queue = vnet_select_queue,
14221434
#ifdef CONFIG_NET_POLL_CONTROLLER
14231435
.ndo_poll_controller = vnet_poll_controller,
14241436
#endif
@@ -1430,7 +1442,7 @@ static struct vnet *vnet_new(const u64 *local_mac)
14301442
struct vnet *vp;
14311443
int err, i;
14321444

1433-
dev = alloc_etherdev(sizeof(*vp));
1445+
dev = alloc_etherdev_mqs(sizeof(*vp), VNET_MAX_TXQS, 1);
14341446
if (!dev)
14351447
return ERR_PTR(-ENOMEM);
14361448
dev->needed_headroom = VNET_PACKET_SKIP + 8;
@@ -1555,6 +1567,25 @@ static void print_version(void)
15551567

15561568
const char *remote_macaddr_prop = "remote-mac-address";
15571569

1570+
static void
1571+
vnet_port_add_txq(struct vnet_port *port)
1572+
{
1573+
struct vnet *vp = port->vp;
1574+
int n;
1575+
1576+
n = vp->nports++;
1577+
n = n & (VNET_MAX_TXQS - 1);
1578+
port->q_index = n;
1579+
netif_tx_wake_queue(netdev_get_tx_queue(vp->dev, port->q_index));
1580+
}
1581+
1582+
static void
1583+
vnet_port_rm_txq(struct vnet_port *port)
1584+
{
1585+
port->vp->nports--;
1586+
netif_tx_stop_queue(netdev_get_tx_queue(port->vp->dev, port->q_index));
1587+
}
1588+
15581589
static int vnet_port_probe(struct vio_dev *vdev, const struct vio_device_id *id)
15591590
{
15601591
struct mdesc_handle *hp;
@@ -1623,6 +1654,7 @@ static int vnet_port_probe(struct vio_dev *vdev, const struct vio_device_id *id)
16231654
list_add_tail_rcu(&port->list, &vp->port_list);
16241655
hlist_add_head_rcu(&port->hash,
16251656
&vp->port_hash[vnet_hashfn(port->raddr)]);
1657+
vnet_port_add_txq(port);
16261658
spin_unlock_irqrestore(&vp->lock, flags);
16271659

16281660
dev_set_drvdata(&vdev->dev, port);
@@ -1667,6 +1699,7 @@ static int vnet_port_remove(struct vio_dev *vdev)
16671699

16681700
synchronize_rcu();
16691701
del_timer_sync(&port->clean_timer);
1702+
vnet_port_rm_txq(port);
16701703
netif_napi_del(&port->napi);
16711704
vnet_port_free_tx_bufs(port);
16721705
vio_ldc_free(&port->vio);

drivers/net/ethernet/sun/sunvnet.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ struct vnet_port {
6161
u32 napi_stop_idx;
6262
bool napi_resume;
6363
int rx_event;
64+
u16 q_index;
6465
};
6566

6667
static inline struct vnet_port *to_vnet_port(struct vio_driver_state *vio)
@@ -102,6 +103,7 @@ struct vnet {
102103
struct list_head list;
103104
u64 local_mac;
104105

106+
int nports;
105107
};
106108

107109
#endif /* _SUNVNET_H */

0 commit comments

Comments
 (0)