aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorAndrew J. Bennieston <andrew.bennieston@citrix.com>2014-06-04 05:30:43 -0400
committerDavid S. Miller <davem@davemloft.net>2014-06-04 17:48:16 -0400
commit8d3d53b3e43363e79ab9a9ecc149b06c1314b25d (patch)
tree210f923600d75e52d562ee851ba57de9daaeb5b7 /drivers/net
parente9ce7cb6b107407e4798e8905b18ad8b642766f6 (diff)
xen-netback: Add support for multiple queues
Builds on the refactoring of the previous patch to implement multiple queues between xen-netfront and xen-netback. Writes the maximum supported number of queues into XenStore, and reads the values written by the frontend to determine how many queues to use. Ring references and event channels are read from XenStore on a per-queue basis and rings are connected accordingly. Also adds code to handle the cleanup of any already initialised queues if the initialisation of a subsequent queue fails. Signed-off-by: Andrew J. Bennieston <andrew.bennieston@citrix.com> Acked-by: Wei Liu <wei.liu2@citrix.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/xen-netback/common.h2
-rw-r--r--drivers/net/xen-netback/interface.c23
-rw-r--r--drivers/net/xen-netback/netback.c8
-rw-r--r--drivers/net/xen-netback/xenbus.c101
4 files changed, 116 insertions, 18 deletions
diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h
index b6885cfcc7df..4dd7c4a1923b 100644
--- a/drivers/net/xen-netback/common.h
+++ b/drivers/net/xen-netback/common.h
@@ -237,6 +237,7 @@ struct xenvif *xenvif_alloc(struct device *parent,
237 unsigned int handle); 237 unsigned int handle);
238 238
239int xenvif_init_queue(struct xenvif_queue *queue); 239int xenvif_init_queue(struct xenvif_queue *queue);
240void xenvif_deinit_queue(struct xenvif_queue *queue);
240 241
241int xenvif_connect(struct xenvif_queue *queue, unsigned long tx_ring_ref, 242int xenvif_connect(struct xenvif_queue *queue, unsigned long tx_ring_ref,
242 unsigned long rx_ring_ref, unsigned int tx_evtchn, 243 unsigned long rx_ring_ref, unsigned int tx_evtchn,
@@ -299,5 +300,6 @@ extern bool separate_tx_rx_irq;
299 300
300extern unsigned int rx_drain_timeout_msecs; 301extern unsigned int rx_drain_timeout_msecs;
301extern unsigned int rx_drain_timeout_jiffies; 302extern unsigned int rx_drain_timeout_jiffies;
303extern unsigned int xenvif_max_queues;
302 304
303#endif /* __XEN_NETBACK__COMMON_H__ */ 305#endif /* __XEN_NETBACK__COMMON_H__ */
diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c
index 6005b5d1d404..6929bcb61cf0 100644
--- a/drivers/net/xen-netback/interface.c
+++ b/drivers/net/xen-netback/interface.c
@@ -139,7 +139,6 @@ static void xenvif_wake_queue_callback(unsigned long data)
139static u16 xenvif_select_queue(struct net_device *dev, struct sk_buff *skb, 139static u16 xenvif_select_queue(struct net_device *dev, struct sk_buff *skb,
140 void *accel_priv, select_queue_fallback_t fallback) 140 void *accel_priv, select_queue_fallback_t fallback)
141{ 141{
142 struct xenvif *vif = netdev_priv(dev);
143 unsigned int num_queues = dev->real_num_tx_queues; 142 unsigned int num_queues = dev->real_num_tx_queues;
144 u32 hash; 143 u32 hash;
145 u16 queue_index; 144 u16 queue_index;
@@ -436,7 +435,12 @@ struct xenvif *xenvif_alloc(struct device *parent, domid_t domid,
436 char name[IFNAMSIZ] = {}; 435 char name[IFNAMSIZ] = {};
437 436
438 snprintf(name, IFNAMSIZ - 1, "vif%u.%u", domid, handle); 437 snprintf(name, IFNAMSIZ - 1, "vif%u.%u", domid, handle);
439 dev = alloc_netdev_mq(sizeof(struct xenvif), name, ether_setup, 1); 438 /* Allocate a netdev with the max. supported number of queues.
439 * When the guest selects the desired number, it will be updated
440 * via netif_set_real_num_tx_queues().
441 */
442 dev = alloc_netdev_mq(sizeof(struct xenvif), name, ether_setup,
443 xenvif_max_queues);
440 if (dev == NULL) { 444 if (dev == NULL) {
441 pr_warn("Could not allocate netdev for %s\n", name); 445 pr_warn("Could not allocate netdev for %s\n", name);
442 return ERR_PTR(-ENOMEM); 446 return ERR_PTR(-ENOMEM);
@@ -706,6 +710,16 @@ void xenvif_disconnect(struct xenvif *vif)
706 } 710 }
707} 711}
708 712
713/* Reverse the relevant parts of xenvif_init_queue().
714 * Used for queue teardown from xenvif_free(), and on the
715 * error handling paths in xenbus.c:connect().
716 */
717void xenvif_deinit_queue(struct xenvif_queue *queue)
718{
719 free_xenballooned_pages(MAX_PENDING_REQS, queue->mmap_pages);
720 netif_napi_del(&queue->napi);
721}
722
709void xenvif_free(struct xenvif *vif) 723void xenvif_free(struct xenvif *vif)
710{ 724{
711 struct xenvif_queue *queue = NULL; 725 struct xenvif_queue *queue = NULL;
@@ -729,11 +743,8 @@ void xenvif_free(struct xenvif *vif)
729 743
730 for (queue_index = 0; queue_index < num_queues; ++queue_index) { 744 for (queue_index = 0; queue_index < num_queues; ++queue_index) {
731 queue = &vif->queues[queue_index]; 745 queue = &vif->queues[queue_index];
732
733 xenvif_wait_unmap_timeout(queue, worst_case_skb_lifetime); 746 xenvif_wait_unmap_timeout(queue, worst_case_skb_lifetime);
734 free_xenballooned_pages(MAX_PENDING_REQS, queue->mmap_pages); 747 xenvif_deinit_queue(queue);
735
736 netif_napi_del(&queue->napi);
737 } 748 }
738 749
739 /* Free the array of queues. The call below does not require 750 /* Free the array of queues. The call below does not require
diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
index a5484e8cb06e..49efff9b99f4 100644
--- a/drivers/net/xen-netback/netback.c
+++ b/drivers/net/xen-netback/netback.c
@@ -62,6 +62,11 @@ unsigned int rx_drain_timeout_msecs = 10000;
62module_param(rx_drain_timeout_msecs, uint, 0444); 62module_param(rx_drain_timeout_msecs, uint, 0444);
63unsigned int rx_drain_timeout_jiffies; 63unsigned int rx_drain_timeout_jiffies;
64 64
65unsigned int xenvif_max_queues;
66module_param_named(max_queues, xenvif_max_queues, uint, 0644);
67MODULE_PARM_DESC(max_queues,
68 "Maximum number of queues per virtual interface");
69
65/* 70/*
66 * This is the maximum slots a skb can have. If a guest sends a skb 71 * This is the maximum slots a skb can have. If a guest sends a skb
67 * which exceeds this limit it is considered malicious. 72 * which exceeds this limit it is considered malicious.
@@ -1953,6 +1958,9 @@ static int __init netback_init(void)
1953 if (!xen_domain()) 1958 if (!xen_domain())
1954 return -ENODEV; 1959 return -ENODEV;
1955 1960
1961 /* Allow as many queues as there are CPUs, by default */
1962 xenvif_max_queues = num_online_cpus();
1963
1956 if (fatal_skb_slots < XEN_NETBK_LEGACY_SLOTS_MAX) { 1964 if (fatal_skb_slots < XEN_NETBK_LEGACY_SLOTS_MAX) {
1957 pr_info("fatal_skb_slots too small (%d), bump it to XEN_NETBK_LEGACY_SLOTS_MAX (%d)\n", 1965 pr_info("fatal_skb_slots too small (%d), bump it to XEN_NETBK_LEGACY_SLOTS_MAX (%d)\n",
1958 fatal_skb_slots, XEN_NETBK_LEGACY_SLOTS_MAX); 1966 fatal_skb_slots, XEN_NETBK_LEGACY_SLOTS_MAX);
diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c
index 358602f55afa..96c63dc2509e 100644
--- a/drivers/net/xen-netback/xenbus.c
+++ b/drivers/net/xen-netback/xenbus.c
@@ -160,6 +160,12 @@ static int netback_probe(struct xenbus_device *dev,
160 if (err) 160 if (err)
161 pr_debug("Error writing feature-split-event-channels\n"); 161 pr_debug("Error writing feature-split-event-channels\n");
162 162
163 /* Multi-queue support: This is an optional feature. */
164 err = xenbus_printf(XBT_NIL, dev->nodename,
165 "multi-queue-max-queues", "%u", xenvif_max_queues);
166 if (err)
167 pr_debug("Error writing multi-queue-max-queues\n");
168
163 err = xenbus_switch_state(dev, XenbusStateInitWait); 169 err = xenbus_switch_state(dev, XenbusStateInitWait);
164 if (err) 170 if (err)
165 goto fail; 171 goto fail;
@@ -490,9 +496,25 @@ static void connect(struct backend_info *be)
490 struct xenbus_device *dev = be->dev; 496 struct xenbus_device *dev = be->dev;
491 unsigned long credit_bytes, credit_usec; 497 unsigned long credit_bytes, credit_usec;
492 unsigned int queue_index; 498 unsigned int queue_index;
493 unsigned int requested_num_queues = 1; 499 unsigned int requested_num_queues;
494 struct xenvif_queue *queue; 500 struct xenvif_queue *queue;
495 501
502 /* Check whether the frontend requested multiple queues
503 * and read the number requested.
504 */
505 err = xenbus_scanf(XBT_NIL, dev->otherend,
506 "multi-queue-num-queues",
507 "%u", &requested_num_queues);
508 if (err < 0) {
509 requested_num_queues = 1; /* Fall back to single queue */
510 } else if (requested_num_queues > xenvif_max_queues) {
511 /* buggy or malicious guest */
512 xenbus_dev_fatal(dev, err,
513 "guest requested %u queues, exceeding the maximum of %u.",
514 requested_num_queues, xenvif_max_queues);
515 return;
516 }
517
496 err = xen_net_read_mac(dev, be->vif->fe_dev_addr); 518 err = xen_net_read_mac(dev, be->vif->fe_dev_addr);
497 if (err) { 519 if (err) {
498 xenbus_dev_fatal(dev, err, "parsing %s/mac", dev->nodename); 520 xenbus_dev_fatal(dev, err, "parsing %s/mac", dev->nodename);
@@ -502,6 +524,7 @@ static void connect(struct backend_info *be)
502 xen_net_read_rate(dev, &credit_bytes, &credit_usec); 524 xen_net_read_rate(dev, &credit_bytes, &credit_usec);
503 read_xenbus_vif_flags(be); 525 read_xenbus_vif_flags(be);
504 526
527 /* Use the number of queues requested by the frontend */
505 be->vif->queues = vzalloc(requested_num_queues * 528 be->vif->queues = vzalloc(requested_num_queues *
506 sizeof(struct xenvif_queue)); 529 sizeof(struct xenvif_queue));
507 rtnl_lock(); 530 rtnl_lock();
@@ -516,14 +539,33 @@ static void connect(struct backend_info *be)
516 be->vif->dev->name, queue->id); 539 be->vif->dev->name, queue->id);
517 540
518 err = xenvif_init_queue(queue); 541 err = xenvif_init_queue(queue);
519 if (err) 542 if (err) {
543 /* xenvif_init_queue() cleans up after itself on
544 * failure, but we need to clean up any previously
545 * initialised queues. Set num_queues to i so that
546 * earlier queues can be destroyed using the regular
547 * disconnect logic.
548 */
549 rtnl_lock();
550 netif_set_real_num_tx_queues(be->vif->dev, queue_index);
551 rtnl_unlock();
520 goto err; 552 goto err;
553 }
521 554
522 queue->remaining_credit = credit_bytes; 555 queue->remaining_credit = credit_bytes;
523 556
524 err = connect_rings(be, queue); 557 err = connect_rings(be, queue);
525 if (err) 558 if (err) {
559 /* connect_rings() cleans up after itself on failure,
560 * but we need to clean up after xenvif_init_queue() here,
561 * and also clean up any previously initialised queues.
562 */
563 xenvif_deinit_queue(queue);
564 rtnl_lock();
565 netif_set_real_num_tx_queues(be->vif->dev, queue_index);
566 rtnl_unlock();
526 goto err; 567 goto err;
568 }
527 } 569 }
528 570
529 xenvif_carrier_on(be->vif); 571 xenvif_carrier_on(be->vif);
@@ -540,6 +582,8 @@ static void connect(struct backend_info *be)
540 return; 582 return;
541 583
542err: 584err:
585 if (be->vif->dev->real_num_tx_queues > 0)
586 xenvif_disconnect(be->vif); /* Clean up existing queues */
543 vfree(be->vif->queues); 587 vfree(be->vif->queues);
544 be->vif->queues = NULL; 588 be->vif->queues = NULL;
545 rtnl_lock(); 589 rtnl_lock();
@@ -552,32 +596,62 @@ err:
552static int connect_rings(struct backend_info *be, struct xenvif_queue *queue) 596static int connect_rings(struct backend_info *be, struct xenvif_queue *queue)
553{ 597{
554 struct xenbus_device *dev = be->dev; 598 struct xenbus_device *dev = be->dev;
599 unsigned int num_queues = queue->vif->dev->real_num_tx_queues;
555 unsigned long tx_ring_ref, rx_ring_ref; 600 unsigned long tx_ring_ref, rx_ring_ref;
556 unsigned int tx_evtchn, rx_evtchn; 601 unsigned int tx_evtchn, rx_evtchn;
557 int err; 602 int err;
603 char *xspath;
604 size_t xspathsize;
605 const size_t xenstore_path_ext_size = 11; /* sufficient for "/queue-NNN" */
606
607 /* If the frontend requested 1 queue, or we have fallen back
608 * to single queue due to lack of frontend support for multi-
609 * queue, expect the remaining XenStore keys in the toplevel
610 * directory. Otherwise, expect them in a subdirectory called
611 * queue-N.
612 */
613 if (num_queues == 1) {
614 xspath = kzalloc(strlen(dev->otherend) + 1, GFP_KERNEL);
615 if (!xspath) {
616 xenbus_dev_fatal(dev, -ENOMEM,
617 "reading ring references");
618 return -ENOMEM;
619 }
620 strcpy(xspath, dev->otherend);
621 } else {
622 xspathsize = strlen(dev->otherend) + xenstore_path_ext_size;
623 xspath = kzalloc(xspathsize, GFP_KERNEL);
624 if (!xspath) {
625 xenbus_dev_fatal(dev, -ENOMEM,
626 "reading ring references");
627 return -ENOMEM;
628 }
629 snprintf(xspath, xspathsize, "%s/queue-%u", dev->otherend,
630 queue->id);
631 }
558 632
559 err = xenbus_gather(XBT_NIL, dev->otherend, 633 err = xenbus_gather(XBT_NIL, xspath,
560 "tx-ring-ref", "%lu", &tx_ring_ref, 634 "tx-ring-ref", "%lu", &tx_ring_ref,
561 "rx-ring-ref", "%lu", &rx_ring_ref, NULL); 635 "rx-ring-ref", "%lu", &rx_ring_ref, NULL);
562 if (err) { 636 if (err) {
563 xenbus_dev_fatal(dev, err, 637 xenbus_dev_fatal(dev, err,
564 "reading %s/ring-ref", 638 "reading %s/ring-ref",
565 dev->otherend); 639 xspath);
566 return err; 640 goto err;
567 } 641 }
568 642
569 /* Try split event channels first, then single event channel. */ 643 /* Try split event channels first, then single event channel. */
570 err = xenbus_gather(XBT_NIL, dev->otherend, 644 err = xenbus_gather(XBT_NIL, xspath,
571 "event-channel-tx", "%u", &tx_evtchn, 645 "event-channel-tx", "%u", &tx_evtchn,
572 "event-channel-rx", "%u", &rx_evtchn, NULL); 646 "event-channel-rx", "%u", &rx_evtchn, NULL);
573 if (err < 0) { 647 if (err < 0) {
574 err = xenbus_scanf(XBT_NIL, dev->otherend, 648 err = xenbus_scanf(XBT_NIL, xspath,
575 "event-channel", "%u", &tx_evtchn); 649 "event-channel", "%u", &tx_evtchn);
576 if (err < 0) { 650 if (err < 0) {
577 xenbus_dev_fatal(dev, err, 651 xenbus_dev_fatal(dev, err,
578 "reading %s/event-channel(-tx/rx)", 652 "reading %s/event-channel(-tx/rx)",
579 dev->otherend); 653 xspath);
580 return err; 654 goto err;
581 } 655 }
582 rx_evtchn = tx_evtchn; 656 rx_evtchn = tx_evtchn;
583 } 657 }
@@ -590,10 +664,13 @@ static int connect_rings(struct backend_info *be, struct xenvif_queue *queue)
590 "mapping shared-frames %lu/%lu port tx %u rx %u", 664 "mapping shared-frames %lu/%lu port tx %u rx %u",
591 tx_ring_ref, rx_ring_ref, 665 tx_ring_ref, rx_ring_ref,
592 tx_evtchn, rx_evtchn); 666 tx_evtchn, rx_evtchn);
593 return err; 667 goto err;
594 } 668 }
595 669
596 return 0; 670 err = 0;
671err: /* Regular return falls through with err == 0 */
672 kfree(xspath);
673 return err;
597} 674}
598 675
599static int read_xenbus_vif_flags(struct backend_info *be) 676static int read_xenbus_vif_flags(struct backend_info *be)