Page MenuHomeFreeBSD

D1994.id4104.diff
No OneTemporary

D1994.id4104.diff

Index: share/man/man4/em.4
===================================================================
--- share/man/man4/em.4
+++ share/man/man4/em.4
@@ -45,6 +45,16 @@
.Cd "device em"
.Ed
.Pp
+Optional multiqueue support is available via the following kernel
+compile options:
+.Bd -ragged -offset indent
+.Cd "options EM_MULTIQUEUE"
+.Ed
+.Pp
+Note: Activating EM_MULTIQUEUE support will disable MSI-X features
+by default. Until these issues are resolved, activating MSI-X will crash
+your system with EM_MULTIQUEUE enabled.
+.Pp
Alternatively, to load the driver as a
module at boot time, place the following line in
.Xr loader.conf 5 :
@@ -197,6 +207,16 @@
prompt before booting the kernel or stored in
.Xr loader.conf 5 .
.Bl -tag -width indent
+.It Va hw.em.eee_setting
+Disable or Enable Energy Efficient Ethernet. Default 1 (disabled).
+.It Va hw.em.msix
+Enable or Disable MSI-X style interrupts. Default 1 (on) unless
+.Cd "options EM_MULTIQUEUE"
+is defined in which case Default 0 (off).
+.It Va hw.em.smart_pwr_down
+Enable or Disable smart power down features on newer adapters. Default 0 (off).
+.It Va hw.em.sbp
+Show bad packets when in promiscuous mode. Default 0 (off).
.It Va hw.em.rxd
Number of receive descriptors allocated by the driver.
The default value is 1024 for adapters newer than 82547,
@@ -228,6 +248,12 @@
.Va hw.em.tx_int_delay
is non-zero, this tunable limits the maximum delay in which a transmit
interrupt is generated.
+.It Va hw.em.num_queues
+Number of h/w queues that we will run on this adapter. Max 2. Defaults to 1.
+Only valid with kernel configuration
+.Cd "options EM_MULTIQUEUE".
+Not compatible with
+.Va hw.em.msix = 1
.El
.Sh FILES
.Bl -tag -width /dev/led/em*
@@ -271,6 +297,9 @@
.Xr polling 4 ,
.Xr vlan 4 ,
.Xr ifconfig 8
+.Sh NOTES
+Enabling EM_MULTIQUEUE in your kernel configuration will disable MSI-X by
+default. At this time MSI-X support does not work with this option.
.Sh HISTORY
The
.Nm
Index: sys/conf/NOTES
===================================================================
--- sys/conf/NOTES
+++ sys/conf/NOTES
@@ -2983,3 +2983,6 @@
# Module to enable execution of application via emulators like QEMU
options IMAGACT_BINMISC
+
+# Intel em(4) driver
+options EM_MULTIQUEUE # Activate multiqueue features/disable MSI-X
Index: sys/conf/options
===================================================================
--- sys/conf/options
+++ sys/conf/options
@@ -935,3 +935,6 @@
RANDOM_YARROW opt_random.h
RANDOM_FORTUNA opt_random.h
RANDOM_DEBUG opt_random.h
+
+# Intel em(4) driver
+EM_MULTIQUEUE opt_em.h
Index: sys/dev/e1000/e1000_defines.h
===================================================================
--- sys/dev/e1000/e1000_defines.h
+++ sys/dev/e1000/e1000_defines.h
@@ -158,10 +158,12 @@
E1000_RXDEXT_STATERR_CXE | \
E1000_RXDEXT_STATERR_RXE)
+#define E1000_MRQC_RSS_ENABLE_2Q 0x00000001
#define E1000_MRQC_RSS_FIELD_MASK 0xFFFF0000
#define E1000_MRQC_RSS_FIELD_IPV4_TCP 0x00010000
#define E1000_MRQC_RSS_FIELD_IPV4 0x00020000
#define E1000_MRQC_RSS_FIELD_IPV6_TCP_EX 0x00040000
+#define E1000_MRQC_RSS_FIELD_IPV6_EX 0x00080000
#define E1000_MRQC_RSS_FIELD_IPV6 0x00100000
#define E1000_MRQC_RSS_FIELD_IPV6_TCP 0x00200000
Index: sys/dev/e1000/if_em.h
===================================================================
--- sys/dev/e1000/if_em.h
+++ sys/dev/e1000/if_em.h
@@ -249,6 +249,14 @@
* solve it just using this define.
*/
#define EM_EIAC 0x000DC
+/*
+ * 82574 only reports 3 MSI-X vectors by default;
+ * defines assisting with making it report 5 are
+ * located here.
+ */
+#define EM_NVM_PCIE_CTRL 0x1B
+#define EM_NVM_MSIX_N_MASK (0x7 << EM_NVM_MSIX_N_SHIFT)
+#define EM_NVM_MSIX_N_SHIFT 7
/*
* Bus dma allocation structure used by
Index: sys/dev/e1000/if_em.c
===================================================================
--- sys/dev/e1000/if_em.c
+++ sys/dev/e1000/if_em.c
@@ -32,6 +32,7 @@
******************************************************************************/
/*$FreeBSD$*/
+#include "opt_em.h"
#include "opt_inet.h"
#include "opt_inet6.h"
@@ -299,6 +300,8 @@
static void em_handle_rx(void *context, int pending);
static void em_handle_link(void *context, int pending);
+static void em_enable_vectors_82574(struct adapter *);
+
static void em_set_sysctl_value(struct adapter *, const char *,
const char *, int *, int);
static int em_set_flowcntl(SYSCTL_HANDLER_ARGS);
@@ -388,6 +391,12 @@
SYSCTL_INT(_hw_em, OID_AUTO, enable_msix, CTLFLAG_RDTUN, &em_enable_msix, 0,
"Enable MSI-X interrupts");
+#ifdef EM_MULTIQUEUE
+static int em_num_queues = 2;
+SYSCTL_INT(_hw_em, OID_AUTO, num_queues, CTLFLAG_RDTUN, &em_num_queues, 0,
+ "82574 only: Number of queues to configure, 0 indicates autoconfigure");
+#endif
+
/* How many packets rxeof tries to clean at a time */
static int em_rx_process_limit = 100;
SYSCTL_INT(_hw_em, OID_AUTO, rx_process_limit, CTLFLAG_RDTUN,
@@ -458,6 +467,32 @@
return (ENXIO);
}
+/*
+ * 82574 only:
+ * Write a new value to the EEPROM increasing the number of MSIX
+ * vectors from 3 to 5, for proper multiqueue support.
+ */
+static void
+em_enable_vectors_82574(struct adapter *adapter)
+{
+ struct e1000_hw *hw = &adapter->hw;
+ device_t dev = adapter->dev;
+ u16 edata;
+
+ e1000_read_nvm(hw, EM_NVM_PCIE_CTRL, 1, &edata);
+ printf("Current cap: %#06x\n", edata);
+ if (((edata & EM_NVM_MSIX_N_MASK) >> EM_NVM_MSIX_N_SHIFT) != 4
+ && adapter->num_queues > 1) {
+ device_printf(dev, "Writing to eeprom: increasing "
+ "reported MSIX vectors from 3 to 5...\n");
+ edata &= ~(EM_NVM_MSIX_N_MASK);
+ edata |= 4 << EM_NVM_MSIX_N_SHIFT;
+ e1000_write_nvm(hw, EM_NVM_PCIE_CTRL, 1, &edata);
+ e1000_update_nvm_checksum(hw);
+ device_printf(dev, "Writing to eeprom: done\n");
+ }
+}
+
/*********************************************************************
* Device initialization routine
*
@@ -550,6 +585,11 @@
goto err_pci;
}
+ /*
+ * Setup MSI/X or MSI if PCI Express
+ */
+ adapter->msix = em_setup_msix(adapter);
+
e1000_get_bus_info(hw);
/* Set up some sysctls for the tunable interrupt delays */
@@ -964,8 +1004,16 @@
{
struct adapter *adapter = if_getsoftc(ifp);
struct tx_ring *txr = adapter->tx_rings;
- int error;
+ int i, error;
+
+#ifdef EM_MULTIQUEUE
+ if (M_HASHTYPE_GET(m) != M_HASHTYPE_NONE)
+ i = m->m_pkthdr.flowid % adapter->num_queues;
+ else
+ i = curcpu % adapter->num_queues;
+ txr = &adapter->tx_rings[i];
+#endif
if (EM_TX_TRYLOCK(txr)) {
error = em_mq_start_locked(ifp, txr, m);
EM_TX_UNLOCK(txr);
@@ -2437,14 +2485,6 @@
rman_get_bushandle(adapter->memory);
adapter->hw.hw_addr = (u8 *)&adapter->osdep.mem_bus_space_handle;
- /* Default to a single queue */
- adapter->num_queues = 1;
-
- /*
- * Setup MSI/X or MSI if PCI Express
- */
- adapter->msix = em_setup_msix(adapter);
-
adapter->hw.back = &adapter->osdep;
return (0);
@@ -2701,14 +2741,19 @@
device_t dev = adapter->dev;
int val;
+ /* Nearly always going to use one queue */
+ adapter->num_queues = 1;
+
/*
- ** Setup MSI/X for Hartwell: tests have shown
- ** use of two queues to be unstable, and to
- ** provide no great gain anyway, so we simply
- ** seperate the interrupts and use a single queue.
+ ** Try using MSI-X for Hartwell adapters
*/
if ((adapter->hw.mac.type == e1000_82574) &&
(em_enable_msix == TRUE)) {
+#ifdef EM_MULTIQUEUE
+ adapter->num_queues = (em_num_queues == 1) ? 1 : 2;
+ if (adapter->num_queues > 1)
+ em_enable_vectors_82574(adapter);
+#endif
/* Map the MSIX BAR */
int rid = PCIR_BAR(EM_MSIX_BAR);
adapter->msix_mem = bus_alloc_resource_any(dev,
@@ -2720,16 +2765,31 @@
goto msi;
}
val = pci_msix_count(dev);
- /* We only need/want 3 vectors */
+
+#ifdef EM_MULTIQUEUE
+ /* We need 5 vectors in the multiqueue case */
+ if (adapter->num_queues == 2) {
+ if (val >= 5)
+ val = 5;
+ else {
+ adapter->num_queues = 1;
+ device_printf(adapter->dev,
+ "Insufficient MSIX vectors for >1 queue, "
+ "using single queue...\n");
+ goto msix_one;
+ }
+ } else
+#endif
+msix_one:
if (val >= 3)
val = 3;
else {
- device_printf(adapter->dev,
- "MSIX: insufficient vectors, using MSI\n");
+ device_printf(adapter->dev,
+ "Insufficient MSIX vectors, using MSI\n");
goto msi;
}
- if ((pci_alloc_msix(dev, &val) == 0) && (val == 3)) {
+ if ((pci_alloc_msix(dev, &val) == 0)) {
device_printf(adapter->dev,
"Using MSIX interrupts "
"with %d vectors\n", val);
@@ -2750,7 +2810,7 @@
}
val = 1;
if (pci_alloc_msi(dev, &val) == 0) {
- device_printf(adapter->dev,"Using an MSI interrupt\n");
+ device_printf(adapter->dev, "Using an MSI interrupt\n");
return (val);
}
/* Should only happen due to manual configuration */
@@ -4278,12 +4338,54 @@
}
rxcsum = E1000_READ_REG(hw, E1000_RXCSUM);
- if (if_getcapenable(ifp) & IFCAP_RXCSUM)
+ if (if_getcapenable(ifp) & IFCAP_RXCSUM) {
+#ifdef EM_MULTIQUEUE
+ rxcsum |= E1000_RXCSUM_TUOFL |
+ E1000_RXCSUM_IPOFL |
+ E1000_RXCSUM_PCSD;
+#else
rxcsum |= E1000_RXCSUM_TUOFL;
- else
+ E1000_WRITE_REG(hw, E1000_RXCSUM, rxcsum);
+#endif
+ } else
rxcsum &= ~E1000_RXCSUM_TUOFL;
- E1000_WRITE_REG(hw, E1000_RXCSUM, rxcsum);
+
+#ifdef EM_MULTIQUEUE
+ if (adapter->num_queues > 1) {
+ uint32_t rss_key[10];
+ uint32_t reta;
+ int i;
+
+ /*
+ * Configure RSS key
+ */
+ arc4rand(rss_key, sizeof(rss_key), 0);
+ for (i = 0; i < 10; ++i)
+ E1000_WRITE_REG_ARRAY(hw,E1000_RSSRK(0), i, rss_key[i]);
+
+ /*
+ * Configure RSS redirect table in following fashion:
+ * (hash & ring_cnt_mask) == rdr_table[(hash & rdr_table_mask)]
+ */
+ reta = 0;
+ for (i = 0; i < 4; ++i) {
+ uint32_t q;
+ q = (i % 2) << 7;
+ reta |= q << (8 * i);
+ }
+ for (i = 0; i < 32; ++i)
+ E1000_WRITE_REG(hw, E1000_RETA(i), reta);
+
+ E1000_WRITE_REG(hw, E1000_MRQC, E1000_MRQC_RSS_ENABLE_2Q |
+ E1000_MRQC_RSS_FIELD_IPV4_TCP |
+ E1000_MRQC_RSS_FIELD_IPV4 |
+ E1000_MRQC_RSS_FIELD_IPV6_TCP_EX |
+ E1000_MRQC_RSS_FIELD_IPV6_EX |
+ E1000_MRQC_RSS_FIELD_IPV6 |
+ E1000_MRQC_RSS_FIELD_IPV6_TCP);
+#endif
+ }
/*
** XXX TEMPORARY WORKAROUND: on some systems with 82573
** long latencies are observed, like Lenovo X60. This
@@ -4317,7 +4419,6 @@
#endif /* DEV_NETMAP */
E1000_WRITE_REG(hw, E1000_RDT(i), rdt);
}
-
/* Set PTHRESH for improved jumbo performance */
if (((adapter->hw.mac.type == e1000_ich9lan) ||
(adapter->hw.mac.type == e1000_pch2lan) ||

File Metadata

Mime Type
text/plain
Expires
Fri, Oct 24, 3:50 AM (18 h, 3 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
24117205
Default Alt Text
D1994.id4104.diff (10 KB)

Event Timeline