summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorluigi <luigi@FreeBSD.org>2013-05-09 17:07:30 +0000
committerluigi <luigi@FreeBSD.org>2013-05-09 17:07:30 +0000
commitf2445b061d612f9b1548197f7d0d407a3fddfa84 (patch)
tree4012346dfa1cfa1f370bdd2b1e3a313b2be31c03
parent872b0246a59d9de3065dc0c05a1ec085aa5c90fa (diff)
downloadFreeBSD-src-f2445b061d612f9b1548197f7d0d407a3fddfa84.zip
FreeBSD-src-f2445b061d612f9b1548197f7d0d407a3fddfa84.tar.gz
if_lem.c: make sure that lem_rxeof() can drain the entire rx queue
irrespective of the setting of lem_rx_process_limit, while giving a chance to the taskqueue scheduler to act after each chunk. This makes lem_rxeof similar to the one in if_em.c and if_igb.c . if_lem.c and if_em.c: add a sysctl to manually configure the 'itr' moderation register. Approved by: Jack Vogel
-rw-r--r--sys/dev/e1000/if_em.c12
-rw-r--r--sys/dev/e1000/if_em.h1
-rw-r--r--sys/dev/e1000/if_lem.c18
-rw-r--r--sys/dev/e1000/if_lem.h1
4 files changed, 27 insertions, 5 deletions
diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c
index b210d4e..2ca4d3e 100644
--- a/sys/dev/e1000/if_em.c
+++ b/sys/dev/e1000/if_em.c
@@ -335,6 +335,9 @@ MODULE_DEPEND(em, ether, 1, 1, 1);
#define EM_USECS_TO_TICKS(usecs) ((1000 * (usecs) + 512) / 1024)
#define M_TSO_LEN 66
+#define MAX_INTS_PER_SEC 8000
+#define DEFAULT_ITR (1000000000/(MAX_INTS_PER_SEC * 256))
+
/* Allow common code without TSO */
#ifndef CSUM_TSO
#define CSUM_TSO 0
@@ -570,6 +573,11 @@ em_attach(device_t dev)
&adapter->tx_abs_int_delay,
E1000_REGISTER(hw, E1000_TADV),
em_tx_abs_int_delay_dflt);
+ em_add_int_delay_sysctl(adapter, "itr",
+ "interrupt delay limit in usecs/4",
+ &adapter->tx_itr,
+ E1000_REGISTER(hw, E1000_ITR),
+ DEFAULT_ITR);
/* Sysctl for limiting the amount of work done in the taskqueue */
em_set_sysctl_value(adapter, "rx_processing_limit",
@@ -4271,8 +4279,6 @@ em_free_receive_buffers(struct rx_ring *rxr)
* Enable receive unit.
*
**********************************************************************/
-#define MAX_INTS_PER_SEC 8000
-#define DEFAULT_ITR 1000000000/(MAX_INTS_PER_SEC * 256)
static void
em_initialize_receive_unit(struct adapter *adapter)
@@ -5618,6 +5624,8 @@ em_sysctl_int_delay(SYSCTL_HANDLER_ARGS)
return (EINVAL);
info->value = usecs;
ticks = EM_USECS_TO_TICKS(usecs);
+ if (info->offset == E1000_ITR) /* units are 256ns here */
+ ticks *= 4;
adapter = info->adapter;
diff --git a/sys/dev/e1000/if_em.h b/sys/dev/e1000/if_em.h
index f1afbad..09d81d2 100644
--- a/sys/dev/e1000/if_em.h
+++ b/sys/dev/e1000/if_em.h
@@ -429,6 +429,7 @@ struct adapter {
struct em_int_delay_info tx_abs_int_delay;
struct em_int_delay_info rx_int_delay;
struct em_int_delay_info rx_abs_int_delay;
+ struct em_int_delay_info tx_itr;
/* Misc stats maintained by the driver */
unsigned long dropped_pkts;
diff --git a/sys/dev/e1000/if_lem.c b/sys/dev/e1000/if_lem.c
index 0ecf651..553aeef 100644
--- a/sys/dev/e1000/if_lem.c
+++ b/sys/dev/e1000/if_lem.c
@@ -281,6 +281,9 @@ MODULE_DEPEND(lem, ether, 1, 1, 1);
#define EM_TICKS_TO_USECS(ticks) ((1024 * (ticks) + 500) / 1000)
#define EM_USECS_TO_TICKS(usecs) ((1000 * (usecs) + 512) / 1024)
+#define MAX_INTS_PER_SEC 8000
+#define DEFAULT_ITR (1000000000/(MAX_INTS_PER_SEC * 256))
+
static int lem_tx_int_delay_dflt = EM_TICKS_TO_USECS(EM_TIDV);
static int lem_rx_int_delay_dflt = EM_TICKS_TO_USECS(EM_RDTR);
static int lem_tx_abs_int_delay_dflt = EM_TICKS_TO_USECS(EM_TADV);
@@ -442,6 +445,11 @@ lem_attach(device_t dev)
&adapter->tx_abs_int_delay,
E1000_REGISTER(&adapter->hw, E1000_TADV),
lem_tx_abs_int_delay_dflt);
+ lem_add_int_delay_sysctl(adapter, "itr",
+ "interrupt delay limit in usecs/4",
+ &adapter->tx_itr,
+ E1000_REGISTER(&adapter->hw, E1000_ITR),
+ DEFAULT_ITR);
}
/* Sysctls for limiting the amount of work done in the taskqueue */
@@ -1337,12 +1345,16 @@ lem_handle_rxtx(void *context, int pending)
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- lem_rxeof(adapter, adapter->rx_process_limit, NULL);
+ bool more = lem_rxeof(adapter, adapter->rx_process_limit, NULL);
EM_TX_LOCK(adapter);
lem_txeof(adapter);
if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
lem_start_locked(ifp);
EM_TX_UNLOCK(adapter);
+ if (more) {
+ taskqueue_enqueue(adapter->tq, &adapter->rxtx_task);
+ return;
+ }
}
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
@@ -3269,8 +3281,6 @@ lem_setup_receive_structures(struct adapter *adapter)
* Enable receive unit.
*
**********************************************************************/
-#define MAX_INTS_PER_SEC 8000
-#define DEFAULT_ITR 1000000000/(MAX_INTS_PER_SEC * 256)
static void
lem_initialize_receive_unit(struct adapter *adapter)
@@ -4596,6 +4606,8 @@ lem_sysctl_int_delay(SYSCTL_HANDLER_ARGS)
return (EINVAL);
info->value = usecs;
ticks = EM_USECS_TO_TICKS(usecs);
+ if (info->offset == E1000_ITR) /* units are 256ns here */
+ ticks *= 4;
adapter = info->adapter;
diff --git a/sys/dev/e1000/if_lem.h b/sys/dev/e1000/if_lem.h
index c1973e5..235277d 100644
--- a/sys/dev/e1000/if_lem.h
+++ b/sys/dev/e1000/if_lem.h
@@ -363,6 +363,7 @@ struct adapter {
struct em_int_delay_info tx_abs_int_delay;
struct em_int_delay_info rx_int_delay;
struct em_int_delay_info rx_abs_int_delay;
+ struct em_int_delay_info tx_itr;
/*
* Transmit definitions
OpenPOWER on IntegriCloud