From owner-svn-src-stable@FreeBSD.ORG Mon Feb 21 01:08:13 2011 Return-Path: Delivered-To: svn-src-stable@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 5F417106564A; Mon, 21 Feb 2011 01:08:13 +0000 (UTC) (envelope-from yongari@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 4AFD18FC0C; Mon, 21 Feb 2011 01:08:13 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id p1L18DGs050927; Mon, 21 Feb 2011 01:08:13 GMT (envelope-from yongari@svn.freebsd.org) Received: (from yongari@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id p1L18DUG050924; Mon, 21 Feb 2011 01:08:13 GMT (envelope-from yongari@svn.freebsd.org) Message-Id: <201102210108.p1L18DUG050924@svn.freebsd.org> From: Pyun YongHyeon Date: Mon, 21 Feb 2011 01:08:13 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org X-SVN-Group: stable-8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r218903 - in stable/8/sys: dev/re pci X-BeenThere: svn-src-stable@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for all the -stable branches of the src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 21 Feb 2011 01:08:13 -0000 Author: yongari Date: Mon Feb 21 01:08:13 2011 New Revision: 218903 URL: http://svn.freebsd.org/changeset/base/218903 Log: MFC r217499: Implement initial jumbo frame support for RTL8168/8111 C/D/E PCIe GbE controllers. It seems these controllers no longer support multi-fragmented RX buffers such that driver have to allocate physically contiguous buffers. o Retire RL_FLAG_NOJUMBO flag and introduce RL_FLAG_JUMBOV2 to mark controllers that use new jumbo frame scheme. o Configure PCIe max read request size to 4096 for standard frames and reduce it to 512 for jumbo frames. o TSO/checksum offloading is not supported for jumbo frames on these controllers. Reflect it to ioctl handler and driver initialization. o Remove unused rl_stats_no_timeout in softc. o Embed a pointer to structure rl_hwrev into softc to keep track of controller MTU limitation and remove rl_hwrev in softc since that information is available through a pointer to structure rl_hwrev. Special thanks to Realtek for donating sample hardwares which made this possible. H/W donated by: Realtek Semiconductor Corp. Modified: stable/8/sys/dev/re/if_re.c stable/8/sys/pci/if_rlreg.h Directory Properties: stable/8/sys/ (props changed) stable/8/sys/amd64/include/xen/ (props changed) stable/8/sys/cddl/contrib/opensolaris/ (props changed) stable/8/sys/contrib/dev/acpica/ (props changed) stable/8/sys/contrib/pf/ (props changed) Modified: stable/8/sys/dev/re/if_re.c ============================================================================== --- stable/8/sys/dev/re/if_re.c Mon Feb 21 01:05:23 2011 (r218902) +++ stable/8/sys/dev/re/if_re.c Mon Feb 21 01:08:13 2011 (r218903) @@ -189,40 +189,40 @@ static struct rl_type re_devs[] = { }; static struct rl_hwrev re_hwrevs[] = { - { RL_HWREV_8139, RL_8139, "" }, - { RL_HWREV_8139A, RL_8139, "A" }, - { RL_HWREV_8139AG, RL_8139, "A-G" }, - { RL_HWREV_8139B, RL_8139, "B" }, - { RL_HWREV_8130, RL_8139, "8130" }, - { RL_HWREV_8139C, RL_8139, "C" }, - { RL_HWREV_8139D, RL_8139, "8139D/8100B/8100C" }, - { RL_HWREV_8139CPLUS, RL_8139CPLUS, "C+"}, - { RL_HWREV_8168_SPIN1, RL_8169, "8168"}, - { RL_HWREV_8169, RL_8169, "8169"}, - { RL_HWREV_8169S, RL_8169, "8169S"}, - { RL_HWREV_8110S, RL_8169, "8110S"}, - { RL_HWREV_8169_8110SB, RL_8169, "8169SB/8110SB"}, - { RL_HWREV_8169_8110SC, RL_8169, "8169SC/8110SC"}, - { RL_HWREV_8169_8110SBL, RL_8169, "8169SBL/8110SBL"}, - { RL_HWREV_8169_8110SCE, RL_8169, "8169SC/8110SC"}, - { RL_HWREV_8100, RL_8139, "8100"}, - { RL_HWREV_8101, RL_8139, "8101"}, - { RL_HWREV_8100E, RL_8169, "8100E"}, - { RL_HWREV_8101E, RL_8169, "8101E"}, - { RL_HWREV_8102E, RL_8169, "8102E"}, - { RL_HWREV_8102EL, RL_8169, "8102EL"}, - { RL_HWREV_8102EL_SPIN1, RL_8169, "8102EL"}, - { RL_HWREV_8103E, RL_8169, "8103E"}, - { RL_HWREV_8168_SPIN2, RL_8169, "8168"}, - { RL_HWREV_8168_SPIN3, RL_8169, "8168"}, - { RL_HWREV_8168C, RL_8169, "8168C/8111C"}, - { RL_HWREV_8168C_SPIN2, RL_8169, "8168C/8111C"}, - { RL_HWREV_8168CP, RL_8169, "8168CP/8111CP"}, - { RL_HWREV_8168D, RL_8169, "8168D/8111D"}, - { RL_HWREV_8168DP, RL_8169, "8168DP/8111DP"}, - { RL_HWREV_8168E, RL_8169, "8168E/8111E"}, - { RL_HWREV_8168E_VL, RL_8169, "8168E/8111E-VL"}, - { 0, 0, NULL } + { RL_HWREV_8139, RL_8139, "", RL_MTU }, + { RL_HWREV_8139A, RL_8139, "A", RL_MTU }, + { RL_HWREV_8139AG, RL_8139, "A-G", RL_MTU }, + { RL_HWREV_8139B, RL_8139, "B", RL_MTU }, + { RL_HWREV_8130, RL_8139, "8130", RL_MTU }, + { RL_HWREV_8139C, RL_8139, "C", RL_MTU }, + { RL_HWREV_8139D, RL_8139, "8139D/8100B/8100C", RL_MTU }, + { RL_HWREV_8139CPLUS, RL_8139CPLUS, "C+", RL_MTU }, + { RL_HWREV_8168_SPIN1, RL_8169, "8168", RL_JUMBO_MTU }, + { RL_HWREV_8169, RL_8169, "8169", RL_JUMBO_MTU }, + { RL_HWREV_8169S, RL_8169, "8169S", RL_JUMBO_MTU }, + { RL_HWREV_8110S, RL_8169, "8110S", RL_JUMBO_MTU }, + { RL_HWREV_8169_8110SB, RL_8169, "8169SB/8110SB", RL_JUMBO_MTU }, + { RL_HWREV_8169_8110SC, RL_8169, "8169SC/8110SC", RL_JUMBO_MTU }, + { RL_HWREV_8169_8110SBL, RL_8169, "8169SBL/8110SBL", RL_JUMBO_MTU }, + { RL_HWREV_8169_8110SCE, RL_8169, "8169SC/8110SC", RL_JUMBO_MTU }, + { RL_HWREV_8100, RL_8139, "8100", RL_MTU }, + { RL_HWREV_8101, RL_8139, "8101", RL_MTU }, + { RL_HWREV_8100E, RL_8169, "8100E", RL_MTU }, + { RL_HWREV_8101E, RL_8169, "8101E", RL_MTU }, + { RL_HWREV_8102E, RL_8169, "8102E", RL_MTU }, + { RL_HWREV_8102EL, RL_8169, "8102EL", RL_MTU }, + { RL_HWREV_8102EL_SPIN1, RL_8169, "8102EL", RL_MTU }, + { RL_HWREV_8103E, RL_8169, "8103E", RL_MTU }, + { RL_HWREV_8168_SPIN2, RL_8169, "8168", RL_JUMBO_MTU }, + { RL_HWREV_8168_SPIN3, RL_8169, "8168", RL_JUMBO_MTU }, + { RL_HWREV_8168C, RL_8169, "8168C/8111C", RL_JUMBO_MTU_6K }, + { RL_HWREV_8168C_SPIN2, RL_8169, "8168C/8111C", RL_JUMBO_MTU_6K }, + { RL_HWREV_8168CP, RL_8169, "8168CP/8111CP", RL_JUMBO_MTU_6K }, + { RL_HWREV_8168D, RL_8169, "8168D/8111D", RL_JUMBO_MTU_9K }, + { RL_HWREV_8168DP, RL_8169, "8168DP/8111DP", RL_JUMBO_MTU_9K }, + { RL_HWREV_8168E, RL_8169, "8168E/8111E", RL_JUMBO_MTU_9K}, + { RL_HWREV_8168E_VL, RL_8169, "8168E/8111E-VL", RL_JUMBO_MTU_6K}, + { 0, 0, NULL, 0 } }; static int re_probe (device_t); @@ -236,7 +236,9 @@ static int re_allocmem (device_t, struc static __inline void re_discard_rxbuf (struct rl_softc *, int); static int re_newbuf (struct rl_softc *, int); +static int re_jumbo_newbuf (struct rl_softc *, int); static int re_rx_list_init (struct rl_softc *); +static int re_jrx_list_init (struct rl_softc *); static int re_tx_list_init (struct rl_softc *); #ifdef RE_FIXUP_RX static __inline void re_fixup_rx @@ -274,6 +276,7 @@ static int re_miibus_readreg (device_t, static int re_miibus_writereg (device_t, int, int, int); static void re_miibus_statchg (device_t); +static void re_set_jumbo (struct rl_softc *, int); static void re_set_rxmode (struct rl_softc *); static void re_reset (struct rl_softc *); static void re_setwol (struct rl_softc *); @@ -699,7 +702,7 @@ re_reset(struct rl_softc *sc) if ((sc->rl_flags & RL_FLAG_MACRESET) != 0) CSR_WRITE_1(sc, 0x82, 1); - if (sc->rl_hwrev == RL_HWREV_8169S) + if (sc->rl_hwrev->rl_rev == RL_HWREV_8169S) re_gmii_writereg(sc->rl_dev, 1, 0x0b, 0); } @@ -991,6 +994,17 @@ re_allocmem(device_t dev, struct rl_soft * Allocate map for RX mbufs. */ + if ((sc->rl_flags & RL_FLAG_JUMBOV2) != 0) { + error = bus_dma_tag_create(sc->rl_parent_tag, sizeof(uint64_t), + 0, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, + MJUM9BYTES, 1, MJUM9BYTES, 0, NULL, NULL, + &sc->rl_ldata.rl_jrx_mtag); + if (error) { + device_printf(dev, + "could not allocate jumbo RX DMA tag\n"); + return (error); + } + } error = bus_dma_tag_create(sc->rl_parent_tag, sizeof(uint64_t), 0, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES, 1, MCLBYTES, 0, NULL, NULL, &sc->rl_ldata.rl_rx_mtag); @@ -1082,6 +1096,24 @@ re_allocmem(device_t dev, struct rl_soft /* Create DMA maps for RX buffers */ + if ((sc->rl_flags & RL_FLAG_JUMBOV2) != 0) { + error = bus_dmamap_create(sc->rl_ldata.rl_jrx_mtag, 0, + &sc->rl_ldata.rl_jrx_sparemap); + if (error) { + device_printf(dev, + "could not create spare DMA map for jumbo RX\n"); + return (error); + } + for (i = 0; i < sc->rl_ldata.rl_rx_desc_cnt; i++) { + error = bus_dmamap_create(sc->rl_ldata.rl_jrx_mtag, 0, + &sc->rl_ldata.rl_jrx_desc[i].rx_dmamap); + if (error) { + device_printf(dev, + "could not create DMA map for jumbo RX\n"); + return (error); + } + } + } error = bus_dmamap_create(sc->rl_ldata.rl_rx_mtag, 0, &sc->rl_ldata.rl_rx_sparemap); if (error) { @@ -1197,11 +1229,6 @@ re_attach(device_t dev) msic = 0; if (pci_find_extcap(dev, PCIY_EXPRESS, ®) == 0) { sc->rl_flags |= RL_FLAG_PCIE; - if (devid != RT_DEVICEID_8101E) { - /* Set PCIe maximum read request size to 2048. */ - if (pci_get_max_read_req(dev) < 2048) - pci_set_max_read_req(dev, 2048); - } msic = pci_msi_count(dev); if (bootverbose) device_printf(dev, "MSI count : %d\n", msic); @@ -1276,7 +1303,7 @@ re_attach(device_t dev) while (hw_rev->rl_desc != NULL) { if (hw_rev->rl_rev == hwrev) { sc->rl_type = hw_rev->rl_type; - sc->rl_hwrev = hw_rev->rl_rev; + sc->rl_hwrev = hw_rev; break; } hw_rev++; @@ -1289,26 +1316,23 @@ re_attach(device_t dev) switch (hw_rev->rl_rev) { case RL_HWREV_8139CPLUS: - sc->rl_flags |= RL_FLAG_NOJUMBO | RL_FLAG_FASTETHER | - RL_FLAG_AUTOPAD; + sc->rl_flags |= RL_FLAG_FASTETHER | RL_FLAG_AUTOPAD; break; case RL_HWREV_8100E: case RL_HWREV_8101E: - sc->rl_flags |= RL_FLAG_NOJUMBO | RL_FLAG_PHYWAKE | - RL_FLAG_FASTETHER; + sc->rl_flags |= RL_FLAG_PHYWAKE | RL_FLAG_FASTETHER; break; case RL_HWREV_8102E: case RL_HWREV_8102EL: case RL_HWREV_8102EL_SPIN1: - sc->rl_flags |= RL_FLAG_NOJUMBO | RL_FLAG_PHYWAKE | - RL_FLAG_PAR | RL_FLAG_DESCV2 | RL_FLAG_MACSTAT | - RL_FLAG_FASTETHER | RL_FLAG_CMDSTOP | RL_FLAG_AUTOPAD; + sc->rl_flags |= RL_FLAG_PHYWAKE | RL_FLAG_PAR | RL_FLAG_DESCV2 | + RL_FLAG_MACSTAT | RL_FLAG_FASTETHER | RL_FLAG_CMDSTOP | + RL_FLAG_AUTOPAD; break; case RL_HWREV_8103E: - sc->rl_flags |= RL_FLAG_NOJUMBO | RL_FLAG_PHYWAKE | - RL_FLAG_PAR | RL_FLAG_DESCV2 | RL_FLAG_MACSTAT | - RL_FLAG_FASTETHER | RL_FLAG_CMDSTOP | RL_FLAG_AUTOPAD | - RL_FLAG_MACSLEEP; + sc->rl_flags |= RL_FLAG_PHYWAKE | RL_FLAG_PAR | RL_FLAG_DESCV2 | + RL_FLAG_MACSTAT | RL_FLAG_FASTETHER | RL_FLAG_CMDSTOP | + RL_FLAG_AUTOPAD | RL_FLAG_MACSLEEP; break; case RL_HWREV_8168_SPIN1: case RL_HWREV_8168_SPIN2: @@ -1329,28 +1353,17 @@ re_attach(device_t dev) case RL_HWREV_8168DP: sc->rl_flags |= RL_FLAG_PHYWAKE | RL_FLAG_PAR | RL_FLAG_DESCV2 | RL_FLAG_MACSTAT | RL_FLAG_CMDSTOP | - RL_FLAG_AUTOPAD; - /* - * 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; + RL_FLAG_AUTOPAD | RL_FLAG_JUMBOV2; break; case RL_HWREV_8168E: sc->rl_flags |= RL_FLAG_PHYWAKE | RL_FLAG_PHYWAKE_PM | RL_FLAG_PAR | RL_FLAG_DESCV2 | RL_FLAG_MACSTAT | - RL_FLAG_CMDSTOP | RL_FLAG_AUTOPAD | RL_FLAG_NOJUMBO; + RL_FLAG_CMDSTOP | RL_FLAG_AUTOPAD | RL_FLAG_JUMBOV2; break; case RL_HWREV_8168E_VL: sc->rl_flags |= RL_FLAG_PHYWAKE | RL_FLAG_PAR | RL_FLAG_DESCV2 | RL_FLAG_MACSTAT | RL_FLAG_CMDSTOP | - RL_FLAG_AUTOPAD | RL_FLAG_NOJUMBO; + RL_FLAG_AUTOPAD | RL_FLAG_JUMBOV2; break; case RL_HWREV_8169_8110SB: case RL_HWREV_8169_8110SBL: @@ -1685,7 +1698,17 @@ re_detach(device_t dev) sc->rl_ldata.rl_rx_sparemap); bus_dma_tag_destroy(sc->rl_ldata.rl_rx_mtag); } - + if (sc->rl_ldata.rl_jrx_mtag) { + for (i = 0; i < sc->rl_ldata.rl_rx_desc_cnt; i++) { + if (sc->rl_ldata.rl_jrx_desc[i].rx_dmamap) + bus_dmamap_destroy(sc->rl_ldata.rl_jrx_mtag, + sc->rl_ldata.rl_jrx_desc[i].rx_dmamap); + } + if (sc->rl_ldata.rl_jrx_sparemap) + bus_dmamap_destroy(sc->rl_ldata.rl_jrx_mtag, + sc->rl_ldata.rl_jrx_sparemap); + bus_dma_tag_destroy(sc->rl_ldata.rl_jrx_mtag); + } /* Unload and free the stats buffer and map */ if (sc->rl_ldata.rl_stag) { @@ -1713,7 +1736,11 @@ re_discard_rxbuf(struct rl_softc *sc, in struct rl_rxdesc *rxd; uint32_t cmdstat; - rxd = &sc->rl_ldata.rl_rx_desc[idx]; + if (sc->rl_ifp->if_mtu > RL_MTU && + (sc->rl_flags & RL_FLAG_JUMBOV2) != 0) + rxd = &sc->rl_ldata.rl_jrx_desc[idx]; + else + rxd = &sc->rl_ldata.rl_rx_desc[idx]; desc = &sc->rl_ldata.rl_rx_list[idx]; desc->rl_vlanctl = 0; cmdstat = rxd->rx_size; @@ -1786,6 +1813,59 @@ re_newbuf(struct rl_softc *sc, int idx) return (0); } +static int +re_jumbo_newbuf(struct rl_softc *sc, int idx) +{ + struct mbuf *m; + struct rl_rxdesc *rxd; + bus_dma_segment_t segs[1]; + bus_dmamap_t map; + struct rl_desc *desc; + uint32_t cmdstat; + int error, nsegs; + + m = m_getjcl(M_DONTWAIT, MT_DATA, M_PKTHDR, MJUM9BYTES); + if (m == NULL) + return (ENOBUFS); + m->m_len = m->m_pkthdr.len = MJUM9BYTES; +#ifdef RE_FIXUP_RX + m_adj(m, RE_ETHER_ALIGN); +#endif + error = bus_dmamap_load_mbuf_sg(sc->rl_ldata.rl_jrx_mtag, + sc->rl_ldata.rl_jrx_sparemap, m, segs, &nsegs, BUS_DMA_NOWAIT); + if (error != 0) { + m_freem(m); + return (ENOBUFS); + } + KASSERT(nsegs == 1, ("%s: %d segment returned!", __func__, nsegs)); + + rxd = &sc->rl_ldata.rl_jrx_desc[idx]; + if (rxd->rx_m != NULL) { + bus_dmamap_sync(sc->rl_ldata.rl_jrx_mtag, rxd->rx_dmamap, + BUS_DMASYNC_POSTREAD); + bus_dmamap_unload(sc->rl_ldata.rl_jrx_mtag, rxd->rx_dmamap); + } + + rxd->rx_m = m; + map = rxd->rx_dmamap; + rxd->rx_dmamap = sc->rl_ldata.rl_jrx_sparemap; + rxd->rx_size = segs[0].ds_len; + sc->rl_ldata.rl_jrx_sparemap = map; + bus_dmamap_sync(sc->rl_ldata.rl_jrx_mtag, rxd->rx_dmamap, + BUS_DMASYNC_PREREAD); + + desc = &sc->rl_ldata.rl_rx_list[idx]; + desc->rl_vlanctl = 0; + desc->rl_bufaddr_lo = htole32(RL_ADDR_LO(segs[0].ds_addr)); + desc->rl_bufaddr_hi = htole32(RL_ADDR_HI(segs[0].ds_addr)); + cmdstat = segs[0].ds_len; + if (idx == sc->rl_ldata.rl_rx_desc_cnt - 1) + cmdstat |= RL_RDESC_CMD_EOR; + desc->rl_cmdstat = htole32(cmdstat | RL_RDESC_CMD_OWN); + + return (0); +} + #ifdef RE_FIXUP_RX static __inline void re_fixup_rx(struct mbuf *m) @@ -1855,6 +1935,29 @@ re_rx_list_init(struct rl_softc *sc) return (0); } +static int +re_jrx_list_init(struct rl_softc *sc) +{ + int error, i; + + bzero(sc->rl_ldata.rl_rx_list, + sc->rl_ldata.rl_rx_desc_cnt * sizeof(struct rl_desc)); + for (i = 0; i < sc->rl_ldata.rl_rx_desc_cnt; i++) { + sc->rl_ldata.rl_jrx_desc[i].rx_m = NULL; + if ((error = re_jumbo_newbuf(sc, i)) != 0) + return (error); + } + + bus_dmamap_sync(sc->rl_ldata.rl_rx_list_tag, + sc->rl_ldata.rl_rx_list_map, + BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); + + sc->rl_ldata.rl_rx_prodidx = 0; + sc->rl_head = sc->rl_tail = NULL; + + return (0); +} + /* * RX handler for C+ and 8169. For the gigE chips, we support * the reception of jumbo frames that have been fragmented @@ -1865,14 +1968,18 @@ re_rxeof(struct rl_softc *sc, int *rx_np { struct mbuf *m; struct ifnet *ifp; - int i, total_len; + int i, rxerr, total_len; struct rl_desc *cur_rx; u_int32_t rxstat, rxvlan; - int maxpkt = 16, rx_npkts = 0; + int jumbo, maxpkt = 16, rx_npkts = 0; RL_LOCK_ASSERT(sc); ifp = sc->rl_ifp; + if (ifp->if_mtu > RL_MTU && (sc->rl_flags & RL_FLAG_JUMBOV2) != 0) + jumbo = 1; + else + jumbo = 0; /* Invalidate the descriptor memory */ @@ -1890,9 +1997,21 @@ re_rxeof(struct rl_softc *sc, int *rx_np break; total_len = rxstat & sc->rl_rxlenmask; rxvlan = le32toh(cur_rx->rl_vlanctl); - m = sc->rl_ldata.rl_rx_desc[i].rx_m; + if (jumbo != 0) + m = sc->rl_ldata.rl_jrx_desc[i].rx_m; + else + m = sc->rl_ldata.rl_rx_desc[i].rx_m; - if (!(rxstat & RL_RDESC_STAT_EOF)) { + if ((sc->rl_flags & RL_FLAG_JUMBOV2) != 0 && + (rxstat & (RL_RDESC_STAT_SOF | RL_RDESC_STAT_EOF)) != + (RL_RDESC_STAT_SOF | RL_RDESC_STAT_EOF)) { + /* + * RTL8168C or later controllers do not + * support multi-fragment packet. + */ + re_discard_rxbuf(sc, i); + continue; + } else if ((rxstat & RL_RDESC_STAT_EOF) == 0) { if (re_newbuf(sc, i) != 0) { /* * If this is part of a multi-fragment packet, @@ -1939,27 +2058,36 @@ re_rxeof(struct rl_softc *sc, int *rx_np * if total_len > 2^13-1, both _RXERRSUM and _GIANT will be * set, but if CRC is clear, it will still be a valid frame. */ - if (rxstat & RL_RDESC_STAT_RXERRSUM && !(total_len > 8191 && - (rxstat & RL_RDESC_STAT_ERRS) == RL_RDESC_STAT_GIANT)) { - ifp->if_ierrors++; - /* - * If this is part of a multi-fragment packet, - * discard all the pieces. - */ - if (sc->rl_head != NULL) { - m_freem(sc->rl_head); - sc->rl_head = sc->rl_tail = NULL; + if ((rxstat & RL_RDESC_STAT_RXERRSUM) != 0) { + rxerr = 1; + if ((sc->rl_flags & RL_FLAG_JUMBOV2) == 0 && + total_len > 8191 && + (rxstat & RL_RDESC_STAT_ERRS) == RL_RDESC_STAT_GIANT) + rxerr = 0; + if (rxerr != 0) { + ifp->if_ierrors++; + /* + * If this is part of a multi-fragment packet, + * discard all the pieces. + */ + if (sc->rl_head != NULL) { + m_freem(sc->rl_head); + sc->rl_head = sc->rl_tail = NULL; + } + re_discard_rxbuf(sc, i); + continue; } - re_discard_rxbuf(sc, i); - continue; } /* * If allocating a replacement mbuf fails, * reload the current one. */ - - if (re_newbuf(sc, i) != 0) { + if (jumbo != 0) + rxerr = re_jumbo_newbuf(sc, i); + else + rxerr = re_newbuf(sc, i); + if (rxerr != 0) { ifp->if_iqdrops++; if (sc->rl_head != NULL) { m_freem(sc->rl_head); @@ -1970,9 +2098,13 @@ re_rxeof(struct rl_softc *sc, int *rx_np } if (sc->rl_head != NULL) { - m->m_len = total_len % RE_RX_DESC_BUFLEN; - if (m->m_len == 0) - m->m_len = RE_RX_DESC_BUFLEN; + if (jumbo != 0) + m->m_len = total_len; + else { + m->m_len = total_len % RE_RX_DESC_BUFLEN; + if (m->m_len == 0) + m->m_len = RE_RX_DESC_BUFLEN; + } /* * Special case: if there's 4 bytes or less * in this buffer, the mbuf can be discarded: @@ -2589,6 +2721,59 @@ re_start(struct ifnet *ifp) } static void +re_set_jumbo(struct rl_softc *sc, int jumbo) +{ + + if (sc->rl_hwrev->rl_rev == RL_HWREV_8168E_VL) { + pci_set_max_read_req(sc->rl_dev, 4096); + return; + } + + CSR_WRITE_1(sc, RL_EECMD, RL_EEMODE_WRITECFG); + if (jumbo != 0) { + CSR_WRITE_1(sc, RL_CFG3, CSR_READ_1(sc, RL_CFG3) | + RL_CFG3_JUMBO_EN0); + switch (sc->rl_hwrev->rl_rev) { + case RL_HWREV_8168DP: + break; + case RL_HWREV_8168E: + CSR_WRITE_1(sc, RL_CFG4, CSR_READ_1(sc, RL_CFG4) | + 0x01); + break; + default: + CSR_WRITE_1(sc, RL_CFG4, CSR_READ_1(sc, RL_CFG4) | + RL_CFG4_JUMBO_EN1); + } + } else { + CSR_WRITE_1(sc, RL_CFG3, CSR_READ_1(sc, RL_CFG3) & + ~RL_CFG3_JUMBO_EN0); + switch (sc->rl_hwrev->rl_rev) { + case RL_HWREV_8168DP: + break; + case RL_HWREV_8168E: + CSR_WRITE_1(sc, RL_CFG4, CSR_READ_1(sc, RL_CFG4) & + ~0x01); + break; + default: + CSR_WRITE_1(sc, RL_CFG4, CSR_READ_1(sc, RL_CFG4) & + ~RL_CFG4_JUMBO_EN1); + } + } + CSR_WRITE_1(sc, RL_EECMD, RL_EEMODE_OFF); + + switch (sc->rl_hwrev->rl_rev) { + case RL_HWREV_8168DP: + pci_set_max_read_req(sc->rl_dev, 4096); + break; + default: + if (jumbo != 0) + pci_set_max_read_req(sc->rl_dev, 512); + else + pci_set_max_read_req(sc->rl_dev, 4096); + } +} + +static void re_init(void *xsc) { struct rl_softc *sc = xsc; @@ -2628,10 +2813,39 @@ re_init_locked(struct rl_softc *sc) /* * For C+ mode, initialize the RX descriptors and mbufs. */ - if (re_rx_list_init(sc) != 0) { - device_printf(sc->rl_dev, "no memory for RX buffers\n"); - re_stop(sc); - return; + if ((sc->rl_flags & RL_FLAG_JUMBOV2) != 0) { + if (ifp->if_mtu > RL_MTU) { + if (re_jrx_list_init(sc) != 0) { + device_printf(sc->rl_dev, + "no memory for jumbo RX buffers\n"); + re_stop(sc); + return; + } + /* Disable checksum offloading for jumbo frames. */ + ifp->if_capenable &= ~(IFCAP_HWCSUM | IFCAP_TSO4); + ifp->if_hwassist &= ~(RE_CSUM_FEATURES | CSUM_TSO); + } else { + if (re_rx_list_init(sc) != 0) { + device_printf(sc->rl_dev, + "no memory for RX buffers\n"); + re_stop(sc); + return; + } + } + re_set_jumbo(sc, ifp->if_mtu > RL_MTU); + } else { + if (re_rx_list_init(sc) != 0) { + device_printf(sc->rl_dev, "no memory for RX buffers\n"); + re_stop(sc); + return; + } + if ((sc->rl_flags & RL_FLAG_PCIE) != 0 && + pci_get_device(sc->rl_dev) != RT_DEVICEID_8101E) { + if (ifp->if_mtu > RL_MTU) + pci_set_max_read_req(sc->rl_dev, 512); + else + pci_set_max_read_req(sc->rl_dev, 4096); + } } re_tx_list_init(sc); @@ -2652,12 +2866,12 @@ re_init_locked(struct rl_softc *sc) } else cfg |= RL_CPLUSCMD_RXENB | RL_CPLUSCMD_TXENB; CSR_WRITE_2(sc, RL_CPLUS_CMD, cfg); - if (sc->rl_hwrev == RL_HWREV_8169_8110SC || - sc->rl_hwrev == RL_HWREV_8169_8110SCE) { + if (sc->rl_hwrev->rl_rev == RL_HWREV_8169_8110SC || + sc->rl_hwrev->rl_rev == RL_HWREV_8169_8110SCE) { reg = 0x000fff00; if ((CSR_READ_1(sc, RL_CFG2) & RL_CFG2_PCI66MHZ) != 0) reg |= 0x000000ff; - if (sc->rl_hwrev == RL_HWREV_8169_8110SCE) + if (sc->rl_hwrev->rl_rev == RL_HWREV_8169_8110SCE) reg |= 0x00f00000; CSR_WRITE_4(sc, 0x7c, reg); /* Disable interrupt mitigation. */ @@ -2727,7 +2941,7 @@ re_init_locked(struct rl_softc *sc) /* Configure interrupt moderation. */ if (sc->rl_type == RL_8169) { - switch (sc->rl_hwrev) { + switch (sc->rl_hwrev->rl_rev) { case RL_HWREV_8100E: case RL_HWREV_8101E: case RL_HWREV_8102E: @@ -2790,10 +3004,25 @@ re_init_locked(struct rl_softc *sc) * size so we can receive jumbo frames. */ if (sc->rl_type == RL_8169) { - if ((sc->rl_flags & (RL_FLAG_PCIE | RL_FLAG_NOJUMBO)) == - (RL_FLAG_PCIE | RL_FLAG_NOJUMBO)) + if ((sc->rl_flags & RL_FLAG_JUMBOV2) != 0) { + /* + * For controllers that use new jumbo frame scheme, + * set maximum size of jumbo frame depedning on + * controller revisions. + */ + if (ifp->if_mtu > RL_MTU) + CSR_WRITE_2(sc, RL_MAXRXPKTLEN, + sc->rl_hwrev->rl_max_mtu + + ETHER_VLAN_ENCAP_LEN + ETHER_HDR_LEN + + ETHER_CRC_LEN); + else + CSR_WRITE_2(sc, RL_MAXRXPKTLEN, + RE_RX_DESC_BUFLEN); + } else if ((sc->rl_flags & RL_FLAG_PCIE) != 0 && + sc->rl_hwrev->rl_max_mtu == RL_MTU) { + /* RTL810x has no jumbo frame support. */ CSR_WRITE_2(sc, RL_MAXRXPKTLEN, RE_RX_DESC_BUFLEN); - else + } else CSR_WRITE_2(sc, RL_MAXRXPKTLEN, 16383); } @@ -2860,22 +3089,25 @@ re_ioctl(struct ifnet *ifp, u_long comma switch (command) { case SIOCSIFMTU: - if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > RL_JUMBO_MTU) { - error = EINVAL; - break; - } - if ((sc->rl_flags & RL_FLAG_NOJUMBO) != 0 && - ifr->ifr_mtu > RL_MAX_FRAMELEN) { + if (ifr->ifr_mtu < ETHERMIN || + ifr->ifr_mtu > sc->rl_hwrev->rl_max_mtu) { error = EINVAL; break; } RL_LOCK(sc); - if (ifp->if_mtu != ifr->ifr_mtu) + if (ifp->if_mtu != ifr->ifr_mtu) { ifp->if_mtu = ifr->ifr_mtu; - if (ifp->if_mtu > RL_TSO_MTU && - (ifp->if_capenable & IFCAP_TSO4) != 0) { - ifp->if_capenable &= ~IFCAP_TSO4; - ifp->if_hwassist &= ~CSUM_TSO; + if ((sc->rl_flags & RL_FLAG_JUMBOV2) != 0 && + (ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) { + ifp->if_drv_flags &= ~IFF_DRV_RUNNING; + re_init_locked(sc); + } + if (ifp->if_mtu > RL_TSO_MTU && + (ifp->if_capenable & IFCAP_TSO4) != 0) { + ifp->if_capenable &= ~(IFCAP_TSO4 | + IFCAP_VLAN_HWTSO); + ifp->if_hwassist &= ~CSUM_TSO; + } VLAN_CAPABILITIES(ifp); } RL_UNLOCK(sc); @@ -2973,6 +3205,10 @@ re_ioctl(struct ifnet *ifp, u_long comma ifp->if_capenable &= ~IFCAP_VLAN_HWTSO; reinit = 1; } + if ((sc->rl_flags & RL_FLAG_JUMBOV2) != 0 && + (mask & (IFCAP_HWCSUM | IFCAP_TSO4 | + IFCAP_VLAN_HWTSO)) != 0) + reinit = 1; if ((mask & IFCAP_WOL) != 0 && (ifp->if_capabilities & IFCAP_WOL) != 0) { if ((mask & IFCAP_WOL_UCAST) != 0) Modified: stable/8/sys/pci/if_rlreg.h ============================================================================== --- stable/8/sys/pci/if_rlreg.h Mon Feb 21 01:05:23 2011 (r218902) +++ stable/8/sys/pci/if_rlreg.h Mon Feb 21 01:08:13 2011 (r218903) @@ -429,6 +429,7 @@ #define RL_CFG3_GRANTSEL 0x80 #define RL_CFG3_WOL_MAGIC 0x20 #define RL_CFG3_WOL_LINK 0x10 +#define RL_CFG3_JUMBO_EN0 0x04 /* RTL8168C or later. */ #define RL_CFG3_FAST_B2B 0x01 /* @@ -436,6 +437,7 @@ */ #define RL_CFG4_LWPTN 0x04 #define RL_CFG4_LWPME 0x10 +#define RL_CFG4_JUMBO_EN1 0x02 /* RTL8168C or later. */ /* * Config 5 register @@ -592,6 +594,7 @@ struct rl_hwrev { uint32_t rl_rev; int rl_type; char *rl_desc; + int rl_max_mtu; }; struct rl_mii_frame { @@ -767,6 +770,7 @@ struct rl_stats { #define RL_8139_RX_DESC_CNT 64 #define RL_TX_DESC_CNT RL_8169_TX_DESC_CNT #define RL_RX_DESC_CNT RL_8169_RX_DESC_CNT +#define RL_RX_JUMBO_DESC_CNT RL_RX_DESC_CNT #define RL_NTXSEGS 32 #define RL_RING_ALIGN 256 @@ -801,8 +805,13 @@ struct rl_stats { /* see comment in dev/re/if_re.c */ #define RL_JUMBO_FRAMELEN 7440 -#define RL_JUMBO_MTU (RL_JUMBO_FRAMELEN-ETHER_HDR_LEN-ETHER_CRC_LEN) -#define RL_MAX_FRAMELEN \ +#define RL_JUMBO_MTU \ + (RL_JUMBO_FRAMELEN-ETHER_VLAN_ENCAP_LEN-ETHER_HDR_LEN-ETHER_CRC_LEN) +#define RL_JUMBO_MTU_6K \ + ((6 * 1024) - ETHER_VLAN_ENCAP_LEN - ETHER_HDR_LEN - ETHER_CRC_LEN) +#define RL_JUMBO_MTU_9K \ + ((9 * 1024) - ETHER_VLAN_ENCAP_LEN - ETHER_HDR_LEN - ETHER_CRC_LEN) +#define RL_MTU \ (ETHER_MAX_LEN + ETHER_VLAN_ENCAP_LEN - ETHER_HDR_LEN - ETHER_CRC_LEN) struct rl_txdesc { @@ -819,6 +828,7 @@ struct rl_rxdesc { struct rl_list_data { struct rl_txdesc rl_tx_desc[RL_TX_DESC_CNT]; struct rl_rxdesc rl_rx_desc[RL_RX_DESC_CNT]; + struct rl_rxdesc rl_jrx_desc[RL_RX_JUMBO_DESC_CNT]; int rl_tx_desc_cnt; int rl_rx_desc_cnt; int rl_tx_prodidx; @@ -827,7 +837,9 @@ struct rl_list_data { int rl_tx_free; bus_dma_tag_t rl_tx_mtag; /* mbuf TX mapping tag */ bus_dma_tag_t rl_rx_mtag; /* mbuf RX mapping tag */ + bus_dma_tag_t rl_jrx_mtag; /* mbuf RX mapping tag */ bus_dmamap_t rl_rx_sparemap; + bus_dmamap_t rl_jrx_sparemap; bus_dma_tag_t rl_stag; /* stats mapping tag */ bus_dmamap_t rl_smap; /* stats map */ struct rl_stats *rl_stats; @@ -857,9 +869,9 @@ struct rl_softc { device_t rl_miibus; bus_dma_tag_t rl_parent_tag; uint8_t rl_type; + struct rl_hwrev *rl_hwrev; int rl_eecmd_read; int rl_eewidth; - uint8_t rl_stats_no_timeout; int rl_txthresh; struct rl_chain_data rl_cdata; struct rl_list_data rl_ldata; @@ -868,7 +880,6 @@ struct rl_softc { struct mtx rl_mtx; struct mbuf *rl_head; struct mbuf *rl_tail; - uint32_t rl_hwrev; uint32_t rl_rxlenmask; int rl_testmode; int rl_if_flags; @@ -890,7 +901,7 @@ struct rl_softc { #define RL_FLAG_AUTOPAD 0x0002 #define RL_FLAG_PHYWAKE_PM 0x0004 #define RL_FLAG_PHYWAKE 0x0008 -#define RL_FLAG_NOJUMBO 0x0010 +#define RL_FLAG_JUMBOV2 0x0010 #define RL_FLAG_PAR 0x0020 #define RL_FLAG_DESCV2 0x0040 #define RL_FLAG_MACSTAT 0x0080