aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorAndrew J. Bennieston <andrew.bennieston@citrix.com>2014-06-04 05:30:45 -0400
committerDavid S. Miller <davem@davemloft.net>2014-06-04 17:48:17 -0400
commit50ee60611bf0c7328e5cae438ea5c26590f3f747 (patch)
tree25c371c319d39bee985cc50dd378bff191e7e2d4 /drivers/net
parent2688fcb79498246d45a0fa5900e415bc97661b6f (diff)
xen-netfront: Add support for multiple queues
Build on the refactoring of the previous patch to implement multiple queues between xen-netfront and xen-netback. Check XenStore for multi-queue support, and set up the rings and event channels accordingly. Write ring references and event channels to XenStore in a queue hierarchy if appropriate, or flat when using only one queue. Update the xennet_select_queue() function to choose the queue on which to transmit a packet based on the skb hash result. Signed-off-by: Andrew J. Bennieston <andrew.bennieston@citrix.com> Acked-by: Wei Liu <wei.liu2@citrix.com> Reviewed-by: David Vrabel <david.vrabel@citrix.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/xen-netfront.c170
1 files changed, 134 insertions, 36 deletions
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index af8cd95ec76b..55bf834d6a8c 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -57,6 +57,12 @@
57#include <xen/interface/memory.h> 57#include <xen/interface/memory.h>
58#include <xen/interface/grant_table.h> 58#include <xen/interface/grant_table.h>
59 59
60/* Module parameters */
61static unsigned int xennet_max_queues;
62module_param_named(max_queues, xennet_max_queues, uint, 0644);
63MODULE_PARM_DESC(max_queues,
64 "Maximum number of queues per virtual interface");
65
60static const struct ethtool_ops xennet_ethtool_ops; 66static const struct ethtool_ops xennet_ethtool_ops;
61 67
62struct netfront_cb { 68struct netfront_cb {
@@ -565,10 +571,22 @@ static int xennet_count_skb_frag_slots(struct sk_buff *skb)
565 return pages; 571 return pages;
566} 572}
567 573
568static u16 xennet_select_queue(struct net_device *dev, struct sk_buff *skb) 574static u16 xennet_select_queue(struct net_device *dev, struct sk_buff *skb,
575 void *accel_priv, select_queue_fallback_t fallback)
569{ 576{
570 /* Stub for later implementation of queue selection */ 577 unsigned int num_queues = dev->real_num_tx_queues;
571 return 0; 578 u32 hash;
579 u16 queue_idx;
580
581 /* First, check if there is only one queue */
582 if (num_queues == 1) {
583 queue_idx = 0;
584 } else {
585 hash = skb_get_hash(skb);
586 queue_idx = hash % num_queues;
587 }
588
589 return queue_idx;
572} 590}
573 591
574static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev) 592static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev)
@@ -1316,7 +1334,7 @@ static struct net_device *xennet_create_dev(struct xenbus_device *dev)
1316 struct net_device *netdev; 1334 struct net_device *netdev;
1317 struct netfront_info *np; 1335 struct netfront_info *np;
1318 1336
1319 netdev = alloc_etherdev_mq(sizeof(struct netfront_info), 1); 1337 netdev = alloc_etherdev_mq(sizeof(struct netfront_info), xennet_max_queues);
1320 if (!netdev) 1338 if (!netdev)
1321 return ERR_PTR(-ENOMEM); 1339 return ERR_PTR(-ENOMEM);
1322 1340
@@ -1687,6 +1705,88 @@ static int xennet_init_queue(struct netfront_queue *queue)
1687 return err; 1705 return err;
1688} 1706}
1689 1707
1708static int write_queue_xenstore_keys(struct netfront_queue *queue,
1709 struct xenbus_transaction *xbt, int write_hierarchical)
1710{
1711 /* Write the queue-specific keys into XenStore in the traditional
1712 * way for a single queue, or in a queue subkeys for multiple
1713 * queues.
1714 */
1715 struct xenbus_device *dev = queue->info->xbdev;
1716 int err;
1717 const char *message;
1718 char *path;
1719 size_t pathsize;
1720
1721 /* Choose the correct place to write the keys */
1722 if (write_hierarchical) {
1723 pathsize = strlen(dev->nodename) + 10;
1724 path = kzalloc(pathsize, GFP_KERNEL);
1725 if (!path) {
1726 err = -ENOMEM;
1727 message = "out of memory while writing ring references";
1728 goto error;
1729 }
1730 snprintf(path, pathsize, "%s/queue-%u",
1731 dev->nodename, queue->id);
1732 } else {
1733 path = (char *)dev->nodename;
1734 }
1735
1736 /* Write ring references */
1737 err = xenbus_printf(*xbt, path, "tx-ring-ref", "%u",
1738 queue->tx_ring_ref);
1739 if (err) {
1740 message = "writing tx-ring-ref";
1741 goto error;
1742 }
1743
1744 err = xenbus_printf(*xbt, path, "rx-ring-ref", "%u",
1745 queue->rx_ring_ref);
1746 if (err) {
1747 message = "writing rx-ring-ref";
1748 goto error;
1749 }
1750
1751 /* Write event channels; taking into account both shared
1752 * and split event channel scenarios.
1753 */
1754 if (queue->tx_evtchn == queue->rx_evtchn) {
1755 /* Shared event channel */
1756 err = xenbus_printf(*xbt, path,
1757 "event-channel", "%u", queue->tx_evtchn);
1758 if (err) {
1759 message = "writing event-channel";
1760 goto error;
1761 }
1762 } else {
1763 /* Split event channels */
1764 err = xenbus_printf(*xbt, path,
1765 "event-channel-tx", "%u", queue->tx_evtchn);
1766 if (err) {
1767 message = "writing event-channel-tx";
1768 goto error;
1769 }
1770
1771 err = xenbus_printf(*xbt, path,
1772 "event-channel-rx", "%u", queue->rx_evtchn);
1773 if (err) {
1774 message = "writing event-channel-rx";
1775 goto error;
1776 }
1777 }
1778
1779 if (write_hierarchical)
1780 kfree(path);
1781 return 0;
1782
1783error:
1784 if (write_hierarchical)
1785 kfree(path);
1786 xenbus_dev_fatal(dev, err, "%s", message);
1787 return err;
1788}
1789
1690/* Common code used when first setting up, and when resuming. */ 1790/* Common code used when first setting up, and when resuming. */
1691static int talk_to_netback(struct xenbus_device *dev, 1791static int talk_to_netback(struct xenbus_device *dev,
1692 struct netfront_info *info) 1792 struct netfront_info *info)
@@ -1696,11 +1796,19 @@ static int talk_to_netback(struct xenbus_device *dev,
1696 int err; 1796 int err;
1697 unsigned int feature_split_evtchn; 1797 unsigned int feature_split_evtchn;
1698 unsigned int i = 0; 1798 unsigned int i = 0;
1799 unsigned int max_queues = 0;
1699 struct netfront_queue *queue = NULL; 1800 struct netfront_queue *queue = NULL;
1700 unsigned int num_queues = 1; 1801 unsigned int num_queues = 1;
1701 1802
1702 info->netdev->irq = 0; 1803 info->netdev->irq = 0;
1703 1804
1805 /* Check if backend supports multiple queues */
1806 err = xenbus_scanf(XBT_NIL, info->xbdev->otherend,
1807 "multi-queue-max-queues", "%u", &max_queues);
1808 if (err < 0)
1809 max_queues = 1;
1810 num_queues = min(max_queues, xennet_max_queues);
1811
1704 /* Check feature-split-event-channels */ 1812 /* Check feature-split-event-channels */
1705 err = xenbus_scanf(XBT_NIL, info->xbdev->otherend, 1813 err = xenbus_scanf(XBT_NIL, info->xbdev->otherend,
1706 "feature-split-event-channels", "%u", 1814 "feature-split-event-channels", "%u",
@@ -1765,49 +1873,35 @@ static int talk_to_netback(struct xenbus_device *dev,
1765 } 1873 }
1766 1874
1767again: 1875again:
1768 queue = &info->queues[0]; /* Use first queue only */
1769
1770 err = xenbus_transaction_start(&xbt); 1876 err = xenbus_transaction_start(&xbt);
1771 if (err) { 1877 if (err) {
1772 xenbus_dev_fatal(dev, err, "starting transaction"); 1878 xenbus_dev_fatal(dev, err, "starting transaction");
1773 goto destroy_ring; 1879 goto destroy_ring;
1774 } 1880 }
1775 1881
1776 err = xenbus_printf(xbt, dev->nodename, "tx-ring-ref", "%u", 1882 if (num_queues == 1) {
1777 queue->tx_ring_ref); 1883 err = write_queue_xenstore_keys(&info->queues[0], &xbt, 0); /* flat */
1778 if (err) { 1884 if (err)
1779 message = "writing tx ring-ref"; 1885 goto abort_transaction_no_dev_fatal;
1780 goto abort_transaction;
1781 }
1782 err = xenbus_printf(xbt, dev->nodename, "rx-ring-ref", "%u",
1783 queue->rx_ring_ref);
1784 if (err) {
1785 message = "writing rx ring-ref";
1786 goto abort_transaction;
1787 }
1788
1789 if (queue->tx_evtchn == queue->rx_evtchn) {
1790 err = xenbus_printf(xbt, dev->nodename,
1791 "event-channel", "%u", queue->tx_evtchn);
1792 if (err) {
1793 message = "writing event-channel";
1794 goto abort_transaction;
1795 }
1796 } else { 1886 } else {
1797 err = xenbus_printf(xbt, dev->nodename, 1887 /* Write the number of queues */
1798 "event-channel-tx", "%u", queue->tx_evtchn); 1888 err = xenbus_printf(xbt, dev->nodename, "multi-queue-num-queues",
1889 "%u", num_queues);
1799 if (err) { 1890 if (err) {
1800 message = "writing event-channel-tx"; 1891 message = "writing multi-queue-num-queues";
1801 goto abort_transaction; 1892 goto abort_transaction_no_dev_fatal;
1802 } 1893 }
1803 err = xenbus_printf(xbt, dev->nodename, 1894
1804 "event-channel-rx", "%u", queue->rx_evtchn); 1895 /* Write the keys for each queue */
1805 if (err) { 1896 for (i = 0; i < num_queues; ++i) {
1806 message = "writing event-channel-rx"; 1897 queue = &info->queues[i];
1807 goto abort_transaction; 1898 err = write_queue_xenstore_keys(queue, &xbt, 1); /* hierarchical */
1899 if (err)
1900 goto abort_transaction_no_dev_fatal;
1808 } 1901 }
1809 } 1902 }
1810 1903
1904 /* The remaining keys are not queue-specific */
1811 err = xenbus_printf(xbt, dev->nodename, "request-rx-copy", "%u", 1905 err = xenbus_printf(xbt, dev->nodename, "request-rx-copy", "%u",
1812 1); 1906 1);
1813 if (err) { 1907 if (err) {
@@ -1857,8 +1951,9 @@ again:
1857 return 0; 1951 return 0;
1858 1952
1859 abort_transaction: 1953 abort_transaction:
1860 xenbus_transaction_end(xbt, 1);
1861 xenbus_dev_fatal(dev, err, "%s", message); 1954 xenbus_dev_fatal(dev, err, "%s", message);
1955abort_transaction_no_dev_fatal:
1956 xenbus_transaction_end(xbt, 1);
1862 destroy_ring: 1957 destroy_ring:
1863 xennet_disconnect_backend(info); 1958 xennet_disconnect_backend(info);
1864 kfree(info->queues); 1959 kfree(info->queues);
@@ -2264,6 +2359,9 @@ static int __init netif_init(void)
2264 2359
2265 pr_info("Initialising Xen virtual ethernet driver\n"); 2360 pr_info("Initialising Xen virtual ethernet driver\n");
2266 2361
2362 /* Allow as many queues as there are CPUs, by default */
2363 xennet_max_queues = num_online_cpus();
2364
2267 return xenbus_register_frontend(&netfront_driver); 2365 return xenbus_register_frontend(&netfront_driver);
2268} 2366}
2269module_init(netif_init); 2367module_init(netif_init);