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