From 0de12bf96f30ca2545f48d0cc3945fec9a49a299 Mon Sep 17 00:00:00 2001 From: jsg Date: Tue, 15 Jul 2008 13:21:17 +0000 Subject: [PATCH] Adapt some code from the FreeBSD driver required to make newer PCI Express adapters (ie 8168C*/8102*) work. V2 Checksum offload format in RTL8102 devices not yet supported. No objections from brad@. Thanks to everyone who tested. --- sys/dev/ic/re.c | 110 ++++++++++++++++++++++++++++++---------- sys/dev/ic/rtl81x9reg.h | 20 +++++++- 2 files changed, 103 insertions(+), 27 deletions(-) diff --git a/sys/dev/ic/re.c b/sys/dev/ic/re.c index 10bafe10af3..e12b06ba394 100644 --- a/sys/dev/ic/re.c +++ b/sys/dev/ic/re.c @@ -1,4 +1,4 @@ -/* $OpenBSD: re.c,v 1.83 2008/07/13 05:24:05 jsg Exp $ */ +/* $OpenBSD: re.c,v 1.84 2008/07/15 13:21:17 jsg Exp $ */ /* $FreeBSD: if_re.c,v 1.31 2004/09/04 07:54:05 ru Exp $ */ /* * Copyright (c) 1997, 1998-2003 @@ -568,16 +568,10 @@ re_setmulti(struct rl_softc *sc) * parts. This means we have to write the hash pattern in reverse * order for those devices. */ - switch (sc->sc_hwrev) { - case RL_HWREV_8100E_SPIN1: - case RL_HWREV_8100E_SPIN2: - case RL_HWREV_8101E: - case RL_HWREV_8168_SPIN1: - case RL_HWREV_8168_SPIN2: + if (sc->rl_flags & RL_FLAG_INVMAR) { CSR_WRITE_4(sc, RL_MAR0, swap32(hashes[1])); CSR_WRITE_4(sc, RL_MAR4, swap32(hashes[0])); - break; - default: + } else { CSR_WRITE_4(sc, RL_MAR0, hashes[0]); CSR_WRITE_4(sc, RL_MAR4, hashes[1]); } @@ -867,6 +861,53 @@ re_attach(struct rl_softc *sc, const char *intrstr) sc->sc_hwrev = CSR_READ_4(sc, RL_TXCFG) & RL_TXCFG_HWREV; + switch (sc->sc_hwrev) { + case RL_HWREV_8139CPLUS: + sc->rl_flags |= RL_FLAG_NOJUMBO; + break; + case RL_HWREV_8100E_SPIN1: + case RL_HWREV_8100E_SPIN2: + case RL_HWREV_8101E: + sc->rl_flags |= RL_FLAG_NOJUMBO | RL_FLAG_INVMAR | + RL_FLAG_PHYWAKE; + break; + case RL_HWREV_8102E: + case RL_HWREV_8102EL: + sc->rl_flags |= RL_FLAG_NOJUMBO | RL_FLAG_INVMAR | + RL_FLAG_PHYWAKE | RL_FLAG_DESCV2 | RL_FLAG_MACSTAT; + break; + case RL_HWREV_8168_SPIN1: + case RL_HWREV_8168_SPIN2: + case RL_HWREV_8168_SPIN3: + sc->rl_flags |= RL_FLAG_INVMAR | RL_FLAG_PHYWAKE | + RL_FLAG_MACSTAT; + break; + case RL_HWREV_8168C: + case RL_HWREV_8168C_SPIN2: + case RL_HWREV_8168CP: + sc->rl_flags |= RL_FLAG_INVMAR | RL_FLAG_PHYWAKE | + RL_FLAG_PAR | RL_FLAG_DESCV2 | RL_FLAG_MACSTAT; + /* + * These controllers support jumbo frame but it seems + * that enabling it requires touching additional magic + * registers. Depending on MAC revisions some + * controllers need to disable checksum offload. So + * disable jumbo frame until I have better idea what + * it really requires to make it support. + * RTL8168C/CP : supports up to 6KB jumbo frame. + * RTL8111C/CP : supports up to 9KB jumbo frame. + */ + sc->rl_flags |= RL_FLAG_NOJUMBO; + break; + case RL_HWREV_8169_8110SB: + case RL_HWREV_8169_8110SCd: + case RL_HWREV_8169_8110SBL: + sc->rl_flags |= RL_FLAG_PHYWAKE; + break; + default: + break; + } + /* * Set RX length mask, TX poll request register * and TX descriptor count. @@ -1007,13 +1048,16 @@ re_attach(struct rl_softc *sc, const char *intrstr) ifp->if_start = re_start; ifp->if_watchdog = re_watchdog; ifp->if_init = re_init; - if (sc->sc_hwrev != RL_HWREV_8139CPLUS) + if ((sc->rl_flags & RL_FLAG_NOJUMBO) == 0) ifp->if_hardmtu = RL_JUMBO_MTU; IFQ_SET_MAXLEN(&ifp->if_snd, RL_TX_QLEN); IFQ_SET_READY(&ifp->if_snd); - ifp->if_capabilities = IFCAP_VLAN_MTU | IFCAP_CSUM_IPv4 | - IFCAP_CSUM_TCPv4 | IFCAP_CSUM_UDPv4; + + ifp->if_capabilities = IFCAP_VLAN_MTU; + if ((sc->rl_flags & RL_FLAG_DESCV2) == 0) + ifp->if_capabilities |= IFCAP_CSUM_IPv4 | + IFCAP_CSUM_TCPv4 | IFCAP_CSUM_UDPv4; #if NVLAN > 0 ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING; @@ -1354,17 +1398,22 @@ re_rxeof(struct rl_softc *sc) /* Do RX checksumming */ - /* Check IP header checksum */ - if ((rxstat & RL_RDESC_STAT_PROTOID) && - !(rxstat & RL_RDESC_STAT_IPSUMBAD)) - m->m_pkthdr.csum_flags |= M_IPV4_CSUM_IN_OK; - - /* Check TCP/UDP checksum */ - if ((RL_TCPPKT(rxstat) && - !(rxstat & RL_RDESC_STAT_TCPSUMBAD)) || - (RL_UDPPKT(rxstat) && - !(rxstat & RL_RDESC_STAT_UDPSUMBAD))) - m->m_pkthdr.csum_flags |= M_TCP_CSUM_IN_OK | M_UDP_CSUM_IN_OK; + if (sc->rl_flags & RL_FLAG_DESCV2) { + /* XXX V2 CSUM */ + } else { + /* Check IP header checksum */ + if ((rxstat & RL_RDESC_STAT_PROTOID) && + !(rxstat & RL_RDESC_STAT_IPSUMBAD)) + m->m_pkthdr.csum_flags |= M_IPV4_CSUM_IN_OK; + + /* Check TCP/UDP checksum */ + if ((RL_TCPPKT(rxstat) && + !(rxstat & RL_RDESC_STAT_TCPSUMBAD)) || + (RL_UDPPKT(rxstat) && + !(rxstat & RL_RDESC_STAT_UDPSUMBAD))) + m->m_pkthdr.csum_flags |= M_TCP_CSUM_IN_OK | + M_UDP_CSUM_IN_OK; + } #if NBPFILTER > 0 if (ifp->if_bpf) @@ -1796,6 +1845,7 @@ re_init(struct ifnet *ifp) { struct rl_softc *sc = ifp->if_softc; u_int32_t rxcfg = 0; + u_int16_t cfg; int s; union { u_int32_t align_dummy; @@ -1813,9 +1863,17 @@ re_init(struct ifnet *ifp) * Enable C+ RX and TX mode, as well as RX checksum offload. * We must configure the C+ register before all others. */ - CSR_WRITE_2(sc, RL_CPLUS_CMD, RL_CPLUSCMD_RXENB| - RL_CPLUSCMD_TXENB|RL_CPLUSCMD_PCI_MRW| - RL_CPLUSCMD_RXCSUM_ENB); + cfg = RL_CPLUSCMD_PCI_MRW; + if (ifp->if_capabilities & IFCAP_CSUM_IPv4) + cfg |= RL_CPLUSCMD_RXCSUM_ENB; + if (sc->rl_flags & RL_FLAG_MACSTAT) { + cfg |= RL_CPLUSCMD_MACSTAT_DIS; + /* XXX magic. */ + cfg |= 0x0001; + } else { + cfg |= RL_CPLUSCMD_RXENB | RL_CPLUSCMD_TXENB; + } + CSR_WRITE_2(sc, RL_CPLUS_CMD, cfg); /* * Init our MAC address. Even though the chipset diff --git a/sys/dev/ic/rtl81x9reg.h b/sys/dev/ic/rtl81x9reg.h index ca7bdab6b71..b5492f9f2b4 100644 --- a/sys/dev/ic/rtl81x9reg.h +++ b/sys/dev/ic/rtl81x9reg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: rtl81x9reg.h,v 1.48 2008/07/13 05:24:05 jsg Exp $ */ +/* $OpenBSD: rtl81x9reg.h,v 1.49 2008/07/15 13:21:17 jsg Exp $ */ /* * Copyright (c) 1997, 1998 @@ -419,6 +419,15 @@ #define RL_CPLUSCMD_PCI_DAC 0x0010 /* PCI dual-address cycle only */ #define RL_CPLUSCMD_RXCSUM_ENB 0x0020 /* enable RX checksum offload */ #define RL_CPLUSCMD_VLANSTRIP 0x0040 /* enable VLAN tag stripping */ +#define RL_CPLUSCMD_MACSTAT_DIS 0x0080 /* 8168B/C/CP */ +#define RL_CPLUSCMD_ASF 0x0100 /* 8168C/CP */ +#define RL_CPLUSCMD_DBG_SEL 0x0200 /* 8168C/CP */ +#define RL_CPLUSCMD_FORCE_TXFC 0x0400 /* 8168C/CP */ +#define RL_CPLUSCMD_FORCE_RXFC 0x0800 /* 8168C/CP */ +#define RL_CPLUSCMD_FORCE_HDPX 0x1000 /* 8168C/CP */ +#define RL_CPLUSCMD_NORMAL_MODE 0x2000 /* 8168C/CP */ +#define RL_CPLUSCMD_DBG_ENB 0x4000 /* 8168C/CP */ +#define RL_CPLUSCMD_BIST_ENB 0x8000 /* 8168C/CP */ /* C+ early transmit threshold */ @@ -749,6 +758,15 @@ struct rl_softc { struct timeout timer_handle; int rl_txstart; + u_int32_t rl_flags; +#define RL_FLAG_MSI 0x0001 +#define RL_FLAG_INVMAR 0x0004 +#define RL_FLAG_PHYWAKE 0x0008 +#define RL_FLAG_NOJUMBO 0x0010 +#define RL_FLAG_PAR 0x0020 +#define RL_FLAG_DESCV2 0x0040 +#define RL_FLAG_MACSTAT 0x0080 +#define RL_FLAG_LINK 0x8000 int rl_link; }; -- 2.20.1