Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/netbsd-2]: src/sys/dev/pci Pull up following revision(s) (requested by r...
details: https://anonhg.NetBSD.org/src/rev/a5d753133dee
branches: netbsd-2
changeset: 564446:a5d753133dee
user: tron <tron%NetBSD.org@localhost>
date: Wed Mar 29 21:36:22 2006 +0000
description:
Pull up following revision(s) (requested by riz in ticket #10403):
sys/dev/pci/if_skreg.h: revision 1.6
sys/dev/pci/if_skvar.h: revision 1.9
sys/dev/pci/if_sk.c: revision 1.20 via patch
Not all chips supported by this driver use the same interrupt moderation
timer frequency; Take this into account. Information gathered from
the sk98lin driver for Linux, from Marvell.
Also add sysctl support for changing the interrupt moderation timer at
runtime; each board is controlled independently.
Discussed on tech-net beginning in November 2005.
diffstat:
sys/dev/pci/if_sk.c | 165 ++++++++++++++++++++++++++++++++++++++++++++----
sys/dev/pci/if_skreg.h | 20 +++++-
sys/dev/pci/if_skvar.h | 5 +-
3 files changed, 172 insertions(+), 18 deletions(-)
diffs (truncated from 318 to 300 lines):
diff -r bf036120be9e -r a5d753133dee sys/dev/pci/if_sk.c
--- a/sys/dev/pci/if_sk.c Wed Mar 29 21:32:57 2006 +0000
+++ b/sys/dev/pci/if_sk.c Wed Mar 29 21:36:22 2006 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: if_sk.c,v 1.7.2.3.2.7 2006/03/29 21:32:57 tron Exp $ */
+/* $NetBSD: if_sk.c,v 1.7.2.3.2.8 2006/03/29 21:36:22 tron Exp $ */
/*-
* Copyright (c) 2003 The NetBSD Foundation, Inc.
@@ -134,6 +134,7 @@
#include <sys/device.h>
#include <sys/queue.h>
#include <sys/callout.h>
+#include <sys/sysctl.h>
#include <net/if.h>
#include <net/if_dl.h>
@@ -201,6 +202,8 @@
struct vpd_res *, int);
void sk_vpd_read(struct sk_softc *);
+void sk_update_int_mod(struct sk_softc *);
+
int sk_xmac_miibus_readreg(struct device *, int, int);
void sk_xmac_miibus_writereg(struct device *, int, int, int);
void sk_xmac_miibus_statchg(struct device *);
@@ -247,6 +250,9 @@
#define SK_WIN_CLRBIT_2(sc, reg, x) \
sk_win_write_2(sc, reg, sk_win_read_2(sc, reg) & ~x)
+static int sk_sysctl_handler(SYSCTLFN_PROTO);
+static int sk_root_num;
+
/* supported device vendors */
static const struct sk_product {
pci_vendor_id_t sk_vendor;
@@ -952,6 +958,39 @@
return(error);
}
+void
+sk_update_int_mod(struct sk_softc *sc)
+{
+ u_int32_t sk_imtimer_ticks;
+
+ /*
+ * Configure interrupt moderation. The moderation timer
+ * defers interrupts specified in the interrupt moderation
+ * timer mask based on the timeout specified in the interrupt
+ * moderation timer init register. Each bit in the timer
+ * register represents one tick, so to specify a timeout in
+ * microseconds, we have to multiply by the correct number of
+ * ticks-per-microsecond.
+ */
+ switch (sc->sk_type) {
+ case SK_GENESIS:
+ sk_imtimer_ticks = SK_IMTIMER_TICKS_GENESIS;
+ break;
+ case SK_YUKON_EC:
+ sk_imtimer_ticks = SK_IMTIMER_TICKS_YUKON_EC;
+ break;
+ default:
+ sk_imtimer_ticks = SK_IMTIMER_TICKS_YUKON;
+ }
+ aprint_verbose("%s: interrupt moderation is %d us\n",
+ sc->sk_dev.dv_xname, 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);
+ sc->sk_int_mod_pending = 0;
+}
+
/*
* Lookup: Check the PCI vendor and device, and return a pointer to
* The structure if the IDs match against our list.
@@ -1030,18 +1069,7 @@
/* Enable RAM interface */
sk_win_write_4(sc, SK_RAMCTL, SK_RAMCTL_UNRESET);
- /*
- * Configure interrupt moderation. The moderation timer
- * defers interrupts specified in the interrupt moderation
- * timer mask based on the timeout specified in the interrupt
- * moderation timer init register. Each bit in the timer
- * 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(100));
- 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);
+ sk_update_int_mod(sc);
}
int
@@ -1351,9 +1379,10 @@
const char *intrstr = NULL;
bus_addr_t iobase;
bus_size_t iosize;
- int s;
+ int s, rc, sk_nodenum;
u_int32_t command;
char *revstr;
+ struct sysctlnode *node;
DPRINTFN(2, ("begin skc_attach\n"));
@@ -1627,6 +1656,36 @@
/* Turn on the 'driver is loaded' LED. */
CSR_WRITE_2(sc, SK_LED, SK_LED_GREEN_ON);
+ /* skc sysctl setup */
+
+ sc->sk_int_mod = SK_IM_DEFAULT;
+ sc->sk_int_mod_pending = 0;
+
+ if ((rc = sysctl_createv(&sc->sk_clog, 0, NULL, &node,
+ 0, CTLTYPE_NODE, sc->sk_dev.dv_xname,
+ SYSCTL_DESCR("skc per-controller controls"),
+ NULL, 0, NULL, 0, CTL_HW, sk_root_num, CTL_CREATE,
+ CTL_EOL)) != 0) {
+ aprint_normal("%s: couldn't create sysctl node\n",
+ sc->sk_dev.dv_xname);
+ goto fail;
+ }
+
+ sk_nodenum = node->sysctl_num;
+
+ /* interrupt moderation time in usecs */
+ if ((rc = sysctl_createv(&sc->sk_clog, 0, NULL, &node,
+ CTLFLAG_READWRITE,
+ CTLTYPE_INT, "int_mod",
+ SYSCTL_DESCR("sk interrupt moderation timer"),
+ sk_sysctl_handler, 0, sc,
+ 0, CTL_HW, sk_root_num, sk_nodenum, CTL_CREATE,
+ CTL_EOL)) != 0) {
+ aprint_normal("%s: couldn't create int_mod sysctl node\n",
+ sc->sk_dev.dv_xname);
+ goto fail;
+ }
+
fail:
splx(s);
}
@@ -2179,6 +2238,9 @@
rnd_add_uint32(&sc->rnd_source, status);
#endif
+ if (sc->sk_int_mod_pending)
+ sk_update_int_mod(sc);
+
return (claimed);
}
@@ -2490,6 +2552,7 @@
struct sk_softc *sc = sc_if->sk_softc;
struct mii_data *mii = &sc_if->sk_mii;
int s;
+ u_int32_t imr, sk_imtimer_ticks;
DPRINTFN(1, ("sk_init\n"));
@@ -2592,6 +2655,25 @@
return(ENOBUFS);
}
+ /* Set interrupt moderation if changed via sysctl. */
+ switch (sc->sk_type) {
+ case SK_GENESIS:
+ sk_imtimer_ticks = SK_IMTIMER_TICKS_GENESIS;
+ break;
+ case SK_YUKON_EC:
+ sk_imtimer_ticks = SK_IMTIMER_TICKS_YUKON_EC;
+ break;
+ default:
+ sk_imtimer_ticks = SK_IMTIMER_TICKS_YUKON;
+ }
+ 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));
+ aprint_verbose("%s: interrupt moderation is %d us\n",
+ sc->sk_dev.dv_xname, sc->sk_int_mod);
+ }
+
/* Configure interrupt handling */
CSR_READ_4(sc, SK_ISSR);
if (sc_if->sk_port == SK_PORT_A)
@@ -2633,6 +2715,7 @@
{
struct sk_if_softc *sc_if = ifp->if_softc;
struct sk_softc *sc = sc_if->sk_softc;
+ //struct sk_txmap_entry *dma;
int i;
DPRINTFN(1, ("sk_stop\n"));
@@ -2794,3 +2877,57 @@
}
}
#endif
+
+static int
+sk_sysctl_handler(SYSCTLFN_ARGS)
+{
+ int error, t;
+ struct sysctlnode node;
+ struct sk_softc *sc;
+
+ node = *rnode;
+ sc = node.sysctl_data;
+ t = sc->sk_int_mod;
+ node.sysctl_data = &t;
+ error = sysctl_lookup(SYSCTLFN_CALL(&node));
+ if (error || newp == NULL)
+ return (error);
+
+ if (t < SK_IM_MIN || t > SK_IM_MAX)
+ return (EINVAL);
+
+ /* update the softc with sysctl-changed value, and mark
+ for hardware update */
+ sc->sk_int_mod = t;
+ sc->sk_int_mod_pending = 1;
+ return (0);
+}
+
+/*
+ * Set up sysctl(3) MIB, hw.sk.* - Individual controllers will be
+ * set up in skc_attach()
+ */
+SYSCTL_SETUP(sysctl_sk, "sysctl sk subtree setup")
+{
+ int rc;
+ struct sysctlnode *node;
+
+ if ((rc = sysctl_createv(clog, 0, NULL, NULL,
+ 0, CTLTYPE_NODE, "hw", NULL,
+ NULL, 0, NULL, 0, CTL_HW, CTL_EOL)) != 0) {
+ goto err;
+ }
+
+ if ((rc = sysctl_createv(clog, 0, NULL, &node,
+ 0, CTLTYPE_NODE, "sk",
+ SYSCTL_DESCR("sk interface controls"),
+ NULL, 0, NULL, 0, CTL_HW, CTL_CREATE, CTL_EOL)) != 0) {
+ goto err;
+ }
+
+ sk_root_num = node->sysctl_num;
+ return;
+
+err:
+ printf("%s: syctl_createv failed (rc = %d)\n", __func__, rc);
+}
diff -r bf036120be9e -r a5d753133dee sys/dev/pci/if_skreg.h
--- a/sys/dev/pci/if_skreg.h Wed Mar 29 21:32:57 2006 +0000
+++ b/sys/dev/pci/if_skreg.h Wed Mar 29 21:36:22 2006 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: if_skreg.h,v 1.2.6.1 2005/01/07 12:15:28 jdc Exp $ */
+/* $NetBSD: if_skreg.h,v 1.2.6.2 2006/03/29 21:38:34 tron Exp $ */
/*-
* Copyright (c) 2003 The NetBSD Foundation, Inc.
@@ -357,18 +357,32 @@
#define SK_YUKON 0xB0
#define SK_YUKON_LITE 0xB1
#define SK_YUKON_LP 0xB2
+#define SK_YUKON_XL 0xB3
+#define SK_YUKON_EC_U 0xB4
+#define SK_YUKON_EC 0xB6
+#define SK_YUKON_FE 0xB7
#define SK_YUKON_FAMILY(x) ((x) & 0xB0)
/* known revisions in SK_CONFIG */
#define SK_YUKON_LITE_REV_A0 0x0 /* invented, see test in skc_attach */
#define SK_YUKON_LITE_REV_A1 0x3
#define SK_YUKON_LITE_REV_A3 0x7
+#define SK_YUKON_EC_REV_A1 0x0
+#define SK_YUKON_EC_REV_A2 0x1
+#define SK_YUKON_EC_REV_A3 0x2
+
#define SK_IMCTL_STOP 0x02
#define SK_IMCTL_START 0x04
-#define SK_IMTIMER_TICKS 54
-#define SK_IM_USECS(x) ((x) * SK_IMTIMER_TICKS)
+/* Number of ticks per usec for interrupt moderation */
+#define SK_IMTIMER_TICKS_GENESIS 54
+#define SK_IMTIMER_TICKS_YUKON 78
+#define SK_IMTIMER_TICKS_YUKON_EC 125
+#define SK_IM_USECS(x) ((x) * sk_imtimer_ticks)
+#define SK_IM_MIN 0
+#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
diff -r bf036120be9e -r a5d753133dee sys/dev/pci/if_skvar.h
Home |
Main Index |
Thread Index |
Old Index