aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sfc
diff options
context:
space:
mode:
authorNeil Turton <nturton@solarflare.com>2008-12-13 00:41:06 -0500
committerDavid S. Miller <davem@davemloft.net>2008-12-13 00:57:44 -0500
commit28b581ab0a0aa7bc8b22935779ca3e8d6f651ac7 (patch)
tree900aa9f5950c1efa01cab8c571a97272b3dc0ce3 /drivers/net/sfc
parent84ae48fe4c1fe8b79fac015df6ad0b0937a7ae37 (diff)
sfc: Add option to use a separate channel for TX completions
In a bidirectional forwarding test, we find that the best performance is achieved by sending the TX completion interrupts from one NIC to a CPU which shares an L2 cache with RX completion interrupts from the other NIC. To facilitate this, add an option (through a module parameter) to create separate channels for RX and TX completion with separate IRQs when MSI-X is available. Signed-off-by: Ben Hutchings <bhutchings@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/sfc')
-rw-r--r--drivers/net/sfc/efx.c41
-rw-r--r--drivers/net/sfc/net_driver.h2
2 files changed, 28 insertions, 15 deletions
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c
index 15ae2fcf6416..2faaa965afca 100644
--- a/drivers/net/sfc/efx.c
+++ b/drivers/net/sfc/efx.c
@@ -64,13 +64,15 @@ MODULE_PARM_DESC(lro, "Large receive offload acceleration");
64/* 64/*
65 * Use separate channels for TX and RX events 65 * Use separate channels for TX and RX events
66 * 66 *
67 * Set this to 1 to use separate channels for TX and RX. It allows us to 67 * Set this to 1 to use separate channels for TX and RX. It allows us
68 * apply a higher level of interrupt moderation to TX events. 68 * to control interrupt affinity separately for TX and RX.
69 * 69 *
70 * This is forced to 0 for MSI interrupt mode as the interrupt vector 70 * This is only used in MSI-X interrupt mode
71 * is not written
72 */ 71 */
73static unsigned int separate_tx_and_rx_channels = true; 72static unsigned int separate_tx_channels;
73module_param(separate_tx_channels, uint, 0644);
74MODULE_PARM_DESC(separate_tx_channels,
75 "Use separate channels for TX and RX");
74 76
75/* This is the weight assigned to each of the (per-channel) virtual 77/* This is the weight assigned to each of the (per-channel) virtual
76 * NAPI devices. 78 * NAPI devices.
@@ -846,26 +848,33 @@ static void efx_probe_interrupts(struct efx_nic *efx)
846 if (efx->interrupt_mode == EFX_INT_MODE_MSIX) { 848 if (efx->interrupt_mode == EFX_INT_MODE_MSIX) {
847 struct msix_entry xentries[EFX_MAX_CHANNELS]; 849 struct msix_entry xentries[EFX_MAX_CHANNELS];
848 int wanted_ints; 850 int wanted_ints;
851 int rx_queues;
849 852
850 /* We want one RX queue and interrupt per CPU package 853 /* We want one RX queue and interrupt per CPU package
851 * (or as specified by the rss_cpus module parameter). 854 * (or as specified by the rss_cpus module parameter).
852 * We will need one channel per interrupt. 855 * We will need one channel per interrupt.
853 */ 856 */
854 wanted_ints = rss_cpus ? rss_cpus : efx_wanted_rx_queues(); 857 rx_queues = rss_cpus ? rss_cpus : efx_wanted_rx_queues();
855 efx->n_rx_queues = min(wanted_ints, max_channels); 858 wanted_ints = rx_queues + (separate_tx_channels ? 1 : 0);
859 wanted_ints = min(wanted_ints, max_channels);
856 860
857 for (i = 0; i < efx->n_rx_queues; i++) 861 for (i = 0; i < wanted_ints; i++)
858 xentries[i].entry = i; 862 xentries[i].entry = i;
859 rc = pci_enable_msix(efx->pci_dev, xentries, efx->n_rx_queues); 863 rc = pci_enable_msix(efx->pci_dev, xentries, wanted_ints);
860 if (rc > 0) { 864 if (rc > 0) {
861 EFX_BUG_ON_PARANOID(rc >= efx->n_rx_queues); 865 EFX_ERR(efx, "WARNING: Insufficient MSI-X vectors"
862 efx->n_rx_queues = rc; 866 " available (%d < %d).\n", rc, wanted_ints);
867 EFX_ERR(efx, "WARNING: Performance may be reduced.\n");
868 EFX_BUG_ON_PARANOID(rc >= wanted_ints);
869 wanted_ints = rc;
863 rc = pci_enable_msix(efx->pci_dev, xentries, 870 rc = pci_enable_msix(efx->pci_dev, xentries,
864 efx->n_rx_queues); 871 wanted_ints);
865 } 872 }
866 873
867 if (rc == 0) { 874 if (rc == 0) {
868 for (i = 0; i < efx->n_rx_queues; i++) 875 efx->n_rx_queues = min(rx_queues, wanted_ints);
876 efx->n_channels = wanted_ints;
877 for (i = 0; i < wanted_ints; i++)
869 efx->channel[i].irq = xentries[i].vector; 878 efx->channel[i].irq = xentries[i].vector;
870 } else { 879 } else {
871 /* Fall back to single channel MSI */ 880 /* Fall back to single channel MSI */
@@ -877,6 +886,7 @@ static void efx_probe_interrupts(struct efx_nic *efx)
877 /* Try single interrupt MSI */ 886 /* Try single interrupt MSI */
878 if (efx->interrupt_mode == EFX_INT_MODE_MSI) { 887 if (efx->interrupt_mode == EFX_INT_MODE_MSI) {
879 efx->n_rx_queues = 1; 888 efx->n_rx_queues = 1;
889 efx->n_channels = 1;
880 rc = pci_enable_msi(efx->pci_dev); 890 rc = pci_enable_msi(efx->pci_dev);
881 if (rc == 0) { 891 if (rc == 0) {
882 efx->channel[0].irq = efx->pci_dev->irq; 892 efx->channel[0].irq = efx->pci_dev->irq;
@@ -889,6 +899,7 @@ static void efx_probe_interrupts(struct efx_nic *efx)
889 /* Assume legacy interrupts */ 899 /* Assume legacy interrupts */
890 if (efx->interrupt_mode == EFX_INT_MODE_LEGACY) { 900 if (efx->interrupt_mode == EFX_INT_MODE_LEGACY) {
891 efx->n_rx_queues = 1; 901 efx->n_rx_queues = 1;
902 efx->n_channels = 1 + (separate_tx_channels ? 1 : 0);
892 efx->legacy_irq = efx->pci_dev->irq; 903 efx->legacy_irq = efx->pci_dev->irq;
893 } 904 }
894} 905}
@@ -913,8 +924,8 @@ static void efx_set_channels(struct efx_nic *efx)
913 struct efx_rx_queue *rx_queue; 924 struct efx_rx_queue *rx_queue;
914 925
915 efx_for_each_tx_queue(tx_queue, efx) { 926 efx_for_each_tx_queue(tx_queue, efx) {
916 if (!EFX_INT_MODE_USE_MSI(efx) && separate_tx_and_rx_channels) 927 if (separate_tx_channels)
917 tx_queue->channel = &efx->channel[1]; 928 tx_queue->channel = &efx->channel[efx->n_channels-1];
918 else 929 else
919 tx_queue->channel = &efx->channel[0]; 930 tx_queue->channel = &efx->channel[0];
920 tx_queue->channel->used_flags |= EFX_USED_BY_TX; 931 tx_queue->channel->used_flags |= EFX_USED_BY_TX;
diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h
index f91060963475..2c5b5fabac1e 100644
--- a/drivers/net/sfc/net_driver.h
+++ b/drivers/net/sfc/net_driver.h
@@ -649,6 +649,7 @@ union efx_multicast_hash {
649 * @rx_queue: RX DMA queues 649 * @rx_queue: RX DMA queues
650 * @channel: Channels 650 * @channel: Channels
651 * @n_rx_queues: Number of RX queues 651 * @n_rx_queues: Number of RX queues
652 * @n_channels: Number of channels in use
652 * @rx_buffer_len: RX buffer length 653 * @rx_buffer_len: RX buffer length
653 * @rx_buffer_order: Order (log2) of number of pages for each RX buffer 654 * @rx_buffer_order: Order (log2) of number of pages for each RX buffer
654 * @irq_status: Interrupt status buffer 655 * @irq_status: Interrupt status buffer
@@ -728,6 +729,7 @@ struct efx_nic {
728 struct efx_channel channel[EFX_MAX_CHANNELS]; 729 struct efx_channel channel[EFX_MAX_CHANNELS];
729 730
730 int n_rx_queues; 731 int n_rx_queues;
732 int n_channels;
731 unsigned int rx_buffer_len; 733 unsigned int rx_buffer_len;
732 unsigned int rx_buffer_order; 734 unsigned int rx_buffer_order;
733 735