summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbz <bz@FreeBSD.org>2005-03-17 14:23:13 +0000
committerbz <bz@FreeBSD.org>2005-03-17 14:23:13 +0000
commite2f49ebf076060ca0bc87c59da336c3d2fa55f6a (patch)
treed110306a530a27a9cf9ad55d839f5e105a84aeeb
parent342779d193ab2d98d6916c776a3aca44abe8a080 (diff)
downloadFreeBSD-src-e2f49ebf076060ca0bc87c59da336c3d2fa55f6a.zip
FreeBSD-src-e2f49ebf076060ca0bc87c59da336c3d2fa55f6a.tar.gz
* Lower interrupt moderation timer 200->100.
Obtained from: NetBSD if_sk.c rev. 1.11 * Make interrupt moderation configurable via sysctl/tuneable. PR: kern/41220 Approved by: rwatson (mentor)
-rw-r--r--sys/dev/sk/if_sk.c61
-rw-r--r--sys/dev/sk/if_skreg.h5
-rw-r--r--sys/pci/if_sk.c61
-rw-r--r--sys/pci/if_skreg.h5
4 files changed, 130 insertions, 2 deletions
diff --git a/sys/dev/sk/if_sk.c b/sys/dev/sk/if_sk.c
index 39c0f8a..16e0c41 100644
--- a/sys/dev/sk/if_sk.c
+++ b/sys/dev/sk/if_sk.c
@@ -94,6 +94,7 @@ __FBSDID("$FreeBSD$");
#include <sys/module.h>
#include <sys/socket.h>
#include <sys/queue.h>
+#include <sys/sysctl.h>
#include <net/if.h>
#include <net/if_arp.h>
@@ -241,6 +242,9 @@ static void sk_setfilt(struct sk_if_softc *, caddr_t, int);
static void sk_setmulti(struct sk_if_softc *);
static void sk_setpromisc(struct sk_if_softc *);
+static int sysctl_int_range(SYSCTL_HANDLER_ARGS, int low, int high);
+static int sysctl_hw_sk_int_mod(SYSCTL_HANDLER_ARGS);
+
#ifdef SK_USEIOSPACE
#define SK_RES SYS_RES_IOPORT
#define SK_RID SK_PCI_LOIO
@@ -1307,7 +1311,9 @@ sk_reset(sc)
* register represents 18.825ns, so to specify a timeout in
* microseconds, we have to multiply by 54.
*/
- sk_win_write_4(sc, SK_IMTIMERINIT, SK_IM_USECS(200));
+ printf("skc%d: interrupt moderation is %d us\n",
+ sc->sk_unit, sc->sk_int_mod);
+ sk_win_write_4(sc, SK_IMTIMERINIT, SK_IM_USECS(sc->sk_int_mod));
sk_win_write_4(sc, SK_IMMR, SK_ISR_TX1_S_EOF|SK_ISR_TX2_S_EOF|
SK_ISR_RX1_EOF|SK_ISR_RX2_EOF);
sk_win_write_1(sc, SK_IMTIMERCTL, SK_IMCTL_START);
@@ -1577,6 +1583,25 @@ skc_attach(dev)
goto fail;
}
+ SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
+ SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
+ OID_AUTO, "int_mod", CTLTYPE_INT|CTLFLAG_RW,
+ &sc->sk_int_mod, 0, sysctl_hw_sk_int_mod, "I",
+ "SK interrupt moderation");
+
+ /* Pull in device tunables. */
+ sc->sk_int_mod = SK_IM_DEFAULT;
+ error = resource_int_value(device_get_name(dev), unit,
+ "int_mod", &sc->sk_int_mod);
+ if (error == 0) {
+ if (sc->sk_int_mod < SK_IM_MIN ||
+ sc->sk_int_mod > SK_IM_MAX) {
+ printf("skc%d: int_mod value out of range; "
+ "using default: %d\n", unit, SK_IM_DEFAULT);
+ sc->sk_int_mod = SK_IM_DEFAULT;
+ }
+ }
+
/* Reset the adapter. */
sk_reset(sc);
@@ -2648,6 +2673,7 @@ sk_init(xsc)
struct ifnet *ifp;
struct mii_data *mii;
u_int16_t reg;
+ u_int32_t imr;
SK_IF_LOCK(sc_if);
@@ -2745,6 +2771,16 @@ sk_init(xsc)
}
sk_init_tx_ring(sc_if);
+ /* Set interrupt moderation if changed via sysctl. */
+ /* SK_LOCK(sc); */
+ imr = sk_win_read_4(sc, SK_IMTIMERINIT);
+ if (imr != SK_IM_USECS(sc->sk_int_mod)) {
+ sk_win_write_4(sc, SK_IMTIMERINIT, SK_IM_USECS(sc->sk_int_mod));
+ printf("skc%d: interrupt moderation is %d us\n",
+ sc->sk_unit, sc->sk_int_mod);
+ }
+ /* SK_UNLOCK(sc); */
+
/* Configure interrupt handling */
CSR_READ_4(sc, SK_ISSR);
if (sc_if->sk_port == SK_PORT_A)
@@ -2864,3 +2900,26 @@ sk_stop(sc_if)
SK_IF_UNLOCK(sc_if);
return;
}
+
+static int
+sysctl_int_range(SYSCTL_HANDLER_ARGS, int low, int high)
+{
+ int error, value;
+
+ if (!arg1)
+ return (EINVAL);
+ value = *(int *)arg1;
+ error = sysctl_handle_int(oidp, &value, 0, req);
+ if (error || !req->newptr)
+ return (error);
+ if (value < low || value > high)
+ return (EINVAL);
+ *(int *)arg1 = value;
+ return (0);
+}
+
+static int
+sysctl_hw_sk_int_mod(SYSCTL_HANDLER_ARGS)
+{
+ return (sysctl_int_range(oidp, arg1, arg2, req, SK_IM_MIN, SK_IM_MAX));
+}
diff --git a/sys/dev/sk/if_skreg.h b/sys/dev/sk/if_skreg.h
index 44d31c3..46e9f1e 100644
--- a/sys/dev/sk/if_skreg.h
+++ b/sys/dev/sk/if_skreg.h
@@ -376,6 +376,10 @@
#define SK_IMTIMER_TICKS 54
#define SK_IM_USECS(x) ((x) * SK_IMTIMER_TICKS)
+#define SK_IM_MIN 10
+#define SK_IM_DEFAULT 100
+#define SK_IM_MAX 10000
+
/*
* The SK_EPROM0 register contains a byte that describes the
* amount of SRAM mounted on the NIC. The value also tells if
@@ -1442,6 +1446,7 @@ struct sk_softc {
u_int32_t sk_ramsize; /* amount of RAM on NIC */
u_int32_t sk_pmd; /* physical media type */
u_int32_t sk_intrmask;
+ int sk_int_mod;
struct sk_if_softc *sk_if[2];
device_t sk_devs[2];
struct mtx sk_mtx;
diff --git a/sys/pci/if_sk.c b/sys/pci/if_sk.c
index 39c0f8a..16e0c41 100644
--- a/sys/pci/if_sk.c
+++ b/sys/pci/if_sk.c
@@ -94,6 +94,7 @@ __FBSDID("$FreeBSD$");
#include <sys/module.h>
#include <sys/socket.h>
#include <sys/queue.h>
+#include <sys/sysctl.h>
#include <net/if.h>
#include <net/if_arp.h>
@@ -241,6 +242,9 @@ static void sk_setfilt(struct sk_if_softc *, caddr_t, int);
static void sk_setmulti(struct sk_if_softc *);
static void sk_setpromisc(struct sk_if_softc *);
+static int sysctl_int_range(SYSCTL_HANDLER_ARGS, int low, int high);
+static int sysctl_hw_sk_int_mod(SYSCTL_HANDLER_ARGS);
+
#ifdef SK_USEIOSPACE
#define SK_RES SYS_RES_IOPORT
#define SK_RID SK_PCI_LOIO
@@ -1307,7 +1311,9 @@ sk_reset(sc)
* register represents 18.825ns, so to specify a timeout in
* microseconds, we have to multiply by 54.
*/
- sk_win_write_4(sc, SK_IMTIMERINIT, SK_IM_USECS(200));
+ printf("skc%d: interrupt moderation is %d us\n",
+ sc->sk_unit, sc->sk_int_mod);
+ sk_win_write_4(sc, SK_IMTIMERINIT, SK_IM_USECS(sc->sk_int_mod));
sk_win_write_4(sc, SK_IMMR, SK_ISR_TX1_S_EOF|SK_ISR_TX2_S_EOF|
SK_ISR_RX1_EOF|SK_ISR_RX2_EOF);
sk_win_write_1(sc, SK_IMTIMERCTL, SK_IMCTL_START);
@@ -1577,6 +1583,25 @@ skc_attach(dev)
goto fail;
}
+ SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
+ SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
+ OID_AUTO, "int_mod", CTLTYPE_INT|CTLFLAG_RW,
+ &sc->sk_int_mod, 0, sysctl_hw_sk_int_mod, "I",
+ "SK interrupt moderation");
+
+ /* Pull in device tunables. */
+ sc->sk_int_mod = SK_IM_DEFAULT;
+ error = resource_int_value(device_get_name(dev), unit,
+ "int_mod", &sc->sk_int_mod);
+ if (error == 0) {
+ if (sc->sk_int_mod < SK_IM_MIN ||
+ sc->sk_int_mod > SK_IM_MAX) {
+ printf("skc%d: int_mod value out of range; "
+ "using default: %d\n", unit, SK_IM_DEFAULT);
+ sc->sk_int_mod = SK_IM_DEFAULT;
+ }
+ }
+
/* Reset the adapter. */
sk_reset(sc);
@@ -2648,6 +2673,7 @@ sk_init(xsc)
struct ifnet *ifp;
struct mii_data *mii;
u_int16_t reg;
+ u_int32_t imr;
SK_IF_LOCK(sc_if);
@@ -2745,6 +2771,16 @@ sk_init(xsc)
}
sk_init_tx_ring(sc_if);
+ /* Set interrupt moderation if changed via sysctl. */
+ /* SK_LOCK(sc); */
+ imr = sk_win_read_4(sc, SK_IMTIMERINIT);
+ if (imr != SK_IM_USECS(sc->sk_int_mod)) {
+ sk_win_write_4(sc, SK_IMTIMERINIT, SK_IM_USECS(sc->sk_int_mod));
+ printf("skc%d: interrupt moderation is %d us\n",
+ sc->sk_unit, sc->sk_int_mod);
+ }
+ /* SK_UNLOCK(sc); */
+
/* Configure interrupt handling */
CSR_READ_4(sc, SK_ISSR);
if (sc_if->sk_port == SK_PORT_A)
@@ -2864,3 +2900,26 @@ sk_stop(sc_if)
SK_IF_UNLOCK(sc_if);
return;
}
+
+static int
+sysctl_int_range(SYSCTL_HANDLER_ARGS, int low, int high)
+{
+ int error, value;
+
+ if (!arg1)
+ return (EINVAL);
+ value = *(int *)arg1;
+ error = sysctl_handle_int(oidp, &value, 0, req);
+ if (error || !req->newptr)
+ return (error);
+ if (value < low || value > high)
+ return (EINVAL);
+ *(int *)arg1 = value;
+ return (0);
+}
+
+static int
+sysctl_hw_sk_int_mod(SYSCTL_HANDLER_ARGS)
+{
+ return (sysctl_int_range(oidp, arg1, arg2, req, SK_IM_MIN, SK_IM_MAX));
+}
diff --git a/sys/pci/if_skreg.h b/sys/pci/if_skreg.h
index 44d31c3..46e9f1e 100644
--- a/sys/pci/if_skreg.h
+++ b/sys/pci/if_skreg.h
@@ -376,6 +376,10 @@
#define SK_IMTIMER_TICKS 54
#define SK_IM_USECS(x) ((x) * SK_IMTIMER_TICKS)
+#define SK_IM_MIN 10
+#define SK_IM_DEFAULT 100
+#define SK_IM_MAX 10000
+
/*
* The SK_EPROM0 register contains a byte that describes the
* amount of SRAM mounted on the NIC. The value also tells if
@@ -1442,6 +1446,7 @@ struct sk_softc {
u_int32_t sk_ramsize; /* amount of RAM on NIC */
u_int32_t sk_pmd; /* physical media type */
u_int32_t sk_intrmask;
+ int sk_int_mod;
struct sk_if_softc *sk_if[2];
device_t sk_devs[2];
struct mtx sk_mtx;
OpenPOWER on IntegriCloud