On Wed, Aug 10, 2005 at 09:19:41PM +0000, Bjoern A. Zeeb wrote: > On Wed, 10 Aug 2005, Juergen Lock wrote: > > Hi, > > > Thanks for the info on your http://sources.zabbadoz.net/freebsd/if_sk.html > > page. Here is a dmesg snippet of another sk problem (Asus A8V deluxe, > > 5.4-R amd64): > > > > skc0: <Marvell Gigabit Ethernet> port 0xa000-0xa0ff mem > > 0xfba00000-0xfba03fff irq 17 at device 10.0 on pci0 > > skc0: Reserved 0x4000 bytes for rid 0x10 type 3 at 0xfba00000 > > skc0: Marvell Yukon Lite Gigabit Ethernet rev. (0x9) > > sk0: <Marvell Semiconductor, Inc. Yukon> on skc0 > > sk0: bpf attached > > sk0: Ethernet address: 00:11:d8:a9:d5:6d > > skc0: no PHY found! > > device_attach: sk0 attach returned 6 > > skc0: [MPSAFE] > > > > Under TODO you have `unkown rev. 0x9 for Yukon Lite', seems this is it? > > Btw i also installed xp on the box and for that i had to fetch the > > latest driver off the marvell.com site too (yk51x86.sys), the one > > distributed by Asus didnt work. (nice, eh?) Linux's sk98lin driver > > (2.6.11 kernel) seems to have no problems tho. > > > > Any patches/info welcome... > > I am currently fixing another problem but in the meantime you can use > this one which should: > > * fix your problem > * catch a bus attach error > * improve locking > > http://sources.zabbadoz.net/freebsd/patchset/EXPERIMENTAL/if_sk.c-rev1.108.diff Thanx. I had to MFC it, but it seems to get the nic working. I haven't tested networking extensively yet tho. (will do that later :)
boot -v dmesg: skc0: <Marvell Gigabit Ethernet> port 0xa000-0xa0ff mem 0xfba00000-0xfba03fff irq 17 at device 10.0 on pci0 skc0: Reserved 0x4000 bytes for rid 0x10 type 3 at 0xfba00000 skc0: interrupt moderation is 100 us skc0: Marvell Yukon Lite Gigabit Ethernet rev. (0x9) skc0: PN: Yukon 88E8001 skc0: EC: Rev. 1.3 skc0: MN: Marvell skc0: SN: AbCdEfG334454 skc0: chip ver = 0xb1 skc0: chip rev = 0x09 skc0: SK_EPROM0 = 0x10 skc0: SRAM size = 0x010000 sk0: <Marvell Semiconductor, Inc. Yukon> on skc0 sk0: bpf attached sk0: Ethernet address: 00:11:d8:a9:d5:6d miibus0: <MII bus> on sk0 e1000phy0: <Marvell 88E1000 Gigabit PHY> on miibus0 e1000phy0: 10baseT, 10baseT-FDX, 100baseTX, 100baseTX-FDX, 1000baseTX-FDX, auto skc0: [MPSAFE] Diff against RELENG_5_4_0_RELEASE: Index: if_sk.c =================================================================== RCS file: /home/ncvs/src/sys/pci/if_sk.c,v retrieving revision 1.83.2.9 diff -u -r1.83.2.9 if_sk.c --- if_sk.c 28 Mar 2005 16:21:16 -0000 1.83.2.9 +++ if_sk.c 10 Aug 2005 22:54:19 -0000 @@ -94,12 +94,14 @@ #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> #include <net/ethernet.h> #include <net/if_dl.h> #include <net/if_media.h> +#include <net/if_types.h> #include <net/bpf.h> @@ -195,8 +197,10 @@ static int sk_encap(struct sk_if_softc *, struct mbuf *, u_int32_t *); static void sk_start(struct ifnet *); +static void sk_start_locked(struct ifnet *); static int sk_ioctl(struct ifnet *, u_long, caddr_t); static void sk_init(void *); +static void sk_init_locked(struct sk_if_softc *); static void sk_init_xmac(struct sk_if_softc *); static void sk_init_yukon(struct sk_if_softc *); static void sk_stop(struct sk_if_softc *); @@ -242,6 +246,9 @@ 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 @@ -474,6 +481,7 @@ free(sc->sk_vpd_readonly, M_DEVBUF); sc->sk_vpd_prodname = NULL; sc->sk_vpd_readonly = NULL; + sc->sk_vpd_readonly_len = 0; sk_vpd_read_res(sc, &res, pos); @@ -491,10 +499,12 @@ pos += sizeof(res); sc->sk_vpd_prodname = malloc(res.vr_len + 1, M_DEVBUF, M_NOWAIT); - for (i = 0; i < res.vr_len; i++) - sc->sk_vpd_prodname[i] = sk_vpd_readbyte(sc, i + pos); - sc->sk_vpd_prodname[i] = '\0'; - pos += i; + if (sc->sk_vpd_prodname != NULL) { + for (i = 0; i < res.vr_len; i++) + sc->sk_vpd_prodname[i] = sk_vpd_readbyte(sc, i + pos); + sc->sk_vpd_prodname[i] = '\0'; + } + pos += res.vr_len; sk_vpd_read_res(sc, &res, pos); @@ -508,6 +518,7 @@ sc->sk_vpd_readonly = malloc(res.vr_len, M_DEVBUF, M_NOWAIT); for (i = 0; i < res.vr_len; i++) sc->sk_vpd_readonly[i] = sk_vpd_readbyte(sc, i + pos); + sc->sk_vpd_readonly_len = res.vr_len; return; } @@ -790,6 +801,7 @@ struct ifmultiaddr *ifma; u_int8_t dummy[] = { 0, 0, 0, 0, 0 ,0 }; + SK_IF_LOCK_ASSERT(sc_if); /* First, zot all the existing filters. */ switch(sc->sk_type) { @@ -877,6 +889,8 @@ struct sk_softc *sc = sc_if->sk_softc; struct ifnet *ifp = &sc_if->arpcom.ac_if; + SK_IF_LOCK_ASSERT(sc_if); + switch(sc->sk_type) { case SK_GENESIS: if (ifp->if_flags & IFF_PROMISC) { @@ -1086,15 +1100,16 @@ sk_free_jumbo_mem(sc_if) struct sk_if_softc *sc_if; { - int retval = 0; struct sk_jpool_entry *entry; SK_JLIST_LOCK(sc_if); - /* Wait for the "inuse" list to drain. */ - if (!SLIST_EMPTY(&sc_if->sk_jinuse_listhead)) - retval = msleep(sc_if, &sc_if->sk_jlist_mtx, PZERO, - "skfjm", 5 * hz); + /* We cannot release external mbuf storage while in use. */ + if (!SLIST_EMPTY(&sc_if->sk_jinuse_listhead)) { + printf("sk%d: will leak jumbo buffer memory!\n", sc_if->sk_unit); + SK_JLIST_UNLOCK(sc_if); + return; + } while (!SLIST_EMPTY(&sc_if->sk_jfree_listhead)) { entry = SLIST_FIRST(&sc_if->sk_jfree_listhead); @@ -1230,13 +1245,15 @@ switch(command) { case SIOCSIFMTU: + SK_IF_LOCK(sc_if); if (ifr->ifr_mtu > SK_JUMBO_MTU) error = EINVAL; else { ifp->if_mtu = ifr->ifr_mtu; ifp->if_flags &= ~IFF_RUNNING; - sk_init(sc_if); + sk_init_locked(sc_if); } + SK_IF_UNLOCK(sc_if); break; case SIOCSIFFLAGS: SK_IF_LOCK(sc_if); @@ -1248,7 +1265,7 @@ sk_setmulti(sc_if); } } else - sk_init(sc_if); + sk_init_locked(sc_if); } else { if (ifp->if_flags & IFF_RUNNING) sk_stop(sc_if); @@ -1259,12 +1276,12 @@ break; case SIOCADDMULTI: case SIOCDELMULTI: + SK_IF_LOCK(sc_if); if (ifp->if_flags & IFF_RUNNING) { - SK_IF_LOCK(sc_if); sk_setmulti(sc_if); - SK_IF_UNLOCK(sc_if); error = 0; } + SK_IF_UNLOCK(sc_if); break; case SIOCGIFMEDIA: case SIOCSIFMEDIA: @@ -1343,7 +1360,10 @@ * 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)); + if (bootverbose) + 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); @@ -1609,6 +1629,25 @@ 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); @@ -1639,7 +1678,7 @@ break; default: printf("skc%d: unknown ram size: %d\n", - sc->sk_unit, sk_win_read_1(sc, SK_EPROM0)); + sc->sk_unit, skrs); error = ENXIO; goto fail; } @@ -1752,16 +1791,74 @@ revstr = ""; } - /* Announce the product name. */ - device_printf(dev, "%s rev. %s(0x%x)\n", pname, revstr, sc->sk_rev); + /* Announce the product name and more VPD data if there. */ + device_printf(dev, "%s rev. %s(0x%x)\n", + pname != NULL ? pname : "<unknown>", revstr, sc->sk_rev); + + if (bootverbose) { + if (sc->sk_vpd_readonly != NULL && + sc->sk_vpd_readonly_len != 0) { + char buf[256]; + char *dp = sc->sk_vpd_readonly; + uint16_t l, len = sc->sk_vpd_readonly_len; + + while (len >= 3) { + if ((*dp == 'P' && *(dp+1) == 'N') || + (*dp == 'E' && *(dp+1) == 'C') || + (*dp == 'M' && *(dp+1) == 'N') || + (*dp == 'S' && *(dp+1) == 'N')) { + l = 0; + while (l < *(dp+2)) { + buf[l] = *(dp+3+l); + ++l; + } + buf[l] = '\0'; + device_printf(dev, "%c%c: %s\n", + *dp, *(dp+1), buf); + len -= (3 + l); + dp += (3 + l); + } else { + len -= (3 + *(dp+2)); + dp += (3 + *(dp+2)); + } + } + } + device_printf(dev, "chip ver = 0x%02x\n", sc->sk_type); + device_printf(dev, "chip rev = 0x%02x\n", sc->sk_rev); + device_printf(dev, "SK_EPROM0 = 0x%02x\n", skrs); + device_printf(dev, "SRAM size = 0x%06x\n", sc->sk_ramsize); + } + sc->sk_devs[SK_PORT_A] = device_add_child(dev, "sk", -1); + if (sc->sk_devs[SK_PORT_A] == NULL) { + device_printf(dev, "failed to add child for PORT_A\n"); + error = ENXIO; + goto fail; + } port = malloc(sizeof(int), M_DEVBUF, M_NOWAIT); + if (port == NULL) { + device_printf(dev, "failed to allocate memory for " + "ivars of PORT_A\n"); + error = ENXIO; + goto fail; + } *port = SK_PORT_A; device_set_ivars(sc->sk_devs[SK_PORT_A], port); if (!(sk_win_read_1(sc, SK_CONFIG) & SK_CONFIG_SINGLEMAC)) { sc->sk_devs[SK_PORT_B] = device_add_child(dev, "sk", -1); + if (sc->sk_devs[SK_PORT_B] == NULL) { + device_printf(dev, "failed to add child for PORT_B\n"); + error = ENXIO; + goto fail; + } port = malloc(sizeof(int), M_DEVBUF, M_NOWAIT); + if (port == NULL) { + device_printf(dev, "failed to allocate memory for " + "ivars of PORT_B\n"); + error = ENXIO; + goto fail; + } *port = SK_PORT_B; device_set_ivars(sc->sk_devs[SK_PORT_B], port); } @@ -1769,7 +1866,11 @@ /* Turn on the 'driver is loaded' LED. */ CSR_WRITE_2(sc, SK_LED, SK_LED_GREEN_ON); - bus_generic_attach(dev); + error = bus_generic_attach(dev); + if (error) { + device_printf(dev, "failed to attach port(s)\n"); + goto fail; + } /* Hook interrupt last to avoid having to lock softc */ error = bus_setup_intr(dev, sc->sk_irq, INTR_TYPE_NET|INTR_MPSAFE, @@ -1930,6 +2031,21 @@ sk_start(ifp) struct ifnet *ifp; { + struct sk_if_softc *sc_if; + + sc_if = ifp->if_softc; + + SK_IF_LOCK(sc_if); + sk_start_locked(ifp); + SK_IF_UNLOCK(sc_if); + + return; +} + +static void +sk_start_locked(ifp) + struct ifnet *ifp; +{ struct sk_softc *sc; struct sk_if_softc *sc_if; struct mbuf *m_head = NULL; @@ -1938,7 +2054,7 @@ sc_if = ifp->if_softc; sc = sc_if->sk_softc; - SK_IF_LOCK(sc_if); + SK_IF_LOCK_ASSERT(sc_if); idx = sc_if->sk_cdata.sk_tx_prod; @@ -1973,7 +2089,6 @@ /* Set a timeout in case the chip goes out to lunch. */ ifp->if_timer = 5; } - SK_IF_UNLOCK(sc_if); return; } @@ -1988,8 +2103,10 @@ sc_if = ifp->if_softc; printf("sk%d: watchdog timeout\n", sc_if->sk_unit); + SK_IF_LOCK(sc_if); ifp->if_flags &= ~IFF_RUNNING; - sk_init(sc_if); + sk_init_locked(sc_if); + SK_IF_UNLOCK(sc_if); return; } @@ -2358,9 +2475,9 @@ CSR_WRITE_4(sc, SK_IMR, sc->sk_intrmask); if (ifp0 != NULL && !IFQ_DRV_IS_EMPTY(&ifp0->if_snd)) - sk_start(ifp0); + sk_start_locked(ifp0); if (ifp1 != NULL && !IFQ_DRV_IS_EMPTY(&ifp1->if_snd)) - sk_start(ifp1); + sk_start_locked(ifp1); SK_UNLOCK(sc); @@ -2546,7 +2663,7 @@ ifp = &sc_if->arpcom.ac_if; if (sc->sk_type == SK_YUKON_LITE && - sc->sk_rev == SK_YUKON_LITE_REV_A3) { + sc->sk_rev >= SK_YUKON_LITE_REV_A3) { /* Take PHY out of reset. */ sk_win_write_4(sc, SK_GPIO, (sk_win_read_4(sc, SK_GPIO) | SK_GPIO_DIR9) & ~SK_GPIO_DAT9); @@ -2650,21 +2767,32 @@ void *xsc; { struct sk_if_softc *sc_if = xsc; + + SK_IF_LOCK(sc_if); + sk_init_locked(sc_if); + SK_IF_UNLOCK(sc_if); + + return; +} + +static void +sk_init_locked(sc_if) + struct sk_if_softc *sc_if; +{ struct sk_softc *sc; struct ifnet *ifp; struct mii_data *mii; u_int16_t reg; + u_int32_t imr; - SK_IF_LOCK(sc_if); + SK_IF_LOCK_ASSERT(sc_if); ifp = &sc_if->arpcom.ac_if; sc = sc_if->sk_softc; mii = device_get_softc(sc_if->sk_miibus); - if (ifp->if_flags & IFF_RUNNING) { - SK_IF_UNLOCK(sc_if); + if (ifp->if_flags & IFF_RUNNING) return; - } /* Cancel pending I/O and free all RX/TX buffers. */ sk_stop(sc_if); @@ -2746,11 +2874,21 @@ printf("sk%d: initialization failed: no " "memory for rx buffers\n", sc_if->sk_unit); sk_stop(sc_if); - SK_IF_UNLOCK(sc_if); return; } 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)); + if (bootverbose) + 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) @@ -2783,8 +2921,6 @@ ifp->if_flags |= IFF_RUNNING; ifp->if_flags &= ~IFF_OACTIVE; - SK_IF_UNLOCK(sc_if); - return; } @@ -2796,7 +2932,7 @@ struct sk_softc *sc; struct ifnet *ifp; - SK_IF_LOCK(sc_if); + SK_IF_LOCK_ASSERT(sc_if); sc = sc_if->sk_softc; ifp = &sc_if->arpcom.ac_if; @@ -2867,6 +3003,29 @@ } ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE); - 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)); +} Index: if_skreg.h =================================================================== RCS file: /home/ncvs/src/sys/pci/if_skreg.h,v retrieving revision 1.20.2.5 diff -u -r1.20.2.5 if_skreg.h --- if_skreg.h 28 Mar 2005 16:21:16 -0000 1.20.2.5 +++ if_skreg.h 10 Aug 2005 22:23:38 -0000 @@ -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 @@ -1437,10 +1441,12 @@ u_int8_t spare; char *sk_vpd_prodname; char *sk_vpd_readonly; + uint16_t sk_vpd_readonly_len; u_int32_t sk_rboff; /* RAMbuffer offset */ 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; _______________________________________________ freebsd-stable@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/freebsd-stable To unsubscribe, send any mail to "[EMAIL PROTECTED]"