hi all,
the below diff enables support for jumbo frames on
some newer re(4) devices. i've tested it on 8186D/8111D
and 8186E/8111E chips, which are both able to do 9k
jumbos. it seems to provide a significant speed-up on
simple file transfer tests. most of the important parts
were taken from the freebsd re(4) driver.
feedback welcome, hope this helps someone.
cheers,
jim
Index: re.c
===================================================================
RCS file: /cvs/src/sys/dev/ic/re.c,v
retrieving revision 1.173
diff -u -r1.173 re.c
--- re.c 21 Jan 2015 10:00:42 -0000 1.173
+++ re.c 21 Jan 2015 11:10:31 -0000
@@ -171,6 +171,8 @@
int re_ifmedia_upd(struct ifnet *);
void re_ifmedia_sts(struct ifnet *, struct ifmediareq *);
+void re_set_jumbo(struct rl_softc *);
+
void re_eeprom_putbyte(struct rl_softc *, int);
void re_eeprom_getword(struct rl_softc *, int, u_int16_t *);
void re_read_eeprom(struct rl_softc *, caddr_t, int, int);
@@ -206,6 +208,10 @@
CSR_WRITE_1(sc, RL_EECMD, \
CSR_READ_1(sc, RL_EECMD) & ~x)
+#define RL_FRAMELEN(mtu) \
+ (mtu + ETHER_HDR_LEN + ETHER_CRC_LEN + \
+ ETHER_VLAN_ENCAP_LEN)
+
static const struct re_revision {
u_int32_t re_chipid;
const char *re_name;
@@ -1022,8 +1028,10 @@
/* Create DMA maps for RX buffers */
for (i = 0; i < RL_RX_DESC_CNT; i++) {
- error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES,
- 0, 0, &sc->rl_ldata.rl_rxsoft[i].rxs_dmamap);
+ error = bus_dmamap_create(sc->sc_dmat,
+ RL_FRAMELEN(sc->rl_max_mtu), 1,
+ RL_FRAMELEN(sc->rl_max_mtu), 0, 0,
+ &sc->rl_ldata.rl_rxsoft[i].rxs_dmamap);
if (error) {
printf("%s: can't create DMA map for RX\n",
sc->sc_dev.dv_xname);
@@ -1038,8 +1046,7 @@
ifp->if_ioctl = re_ioctl;
ifp->if_start = re_start;
ifp->if_watchdog = re_watchdog;
- if ((sc->rl_flags & RL_FLAG_JUMBOV2) == 0)
- ifp->if_hardmtu = sc->rl_max_mtu;
+ ifp->if_hardmtu = sc->rl_max_mtu;
IFQ_SET_MAXLEN(&ifp->if_snd, RL_TX_QLEN);
IFQ_SET_READY(&ifp->if_snd);
@@ -1159,7 +1166,7 @@
u_int32_t cmdstat;
int error, idx;
- m = MCLGETI(NULL, M_DONTWAIT, NULL, MCLBYTES);
+ m = MCLGETI(NULL, M_DONTWAIT, NULL, RL_FRAMELEN(sc->rl_max_mtu));
if (!m)
return (ENOBUFS);
@@ -1168,7 +1175,7 @@
* alignment so that the frame payload is
* longword aligned on strict alignment archs.
*/
- m->m_len = m->m_pkthdr.len = RE_RX_DESC_BUFLEN;
+ m->m_len = m->m_pkthdr.len = RL_FRAMELEN(sc->rl_max_mtu);
m->m_data += RE_ETHER_ALIGN;
idx = sc->rl_ldata.rl_rx_prodidx;
@@ -1274,7 +1281,7 @@
{
struct mbuf *m;
struct ifnet *ifp;
- int i, total_len, rx = 0;
+ int i, total_len, rxerr, rx = 0;
struct rl_desc *cur_rx;
struct rl_rxsoft *rxs;
u_int32_t rxstat, rxvlan;
@@ -1306,8 +1313,12 @@
BUS_DMASYNC_POSTREAD);
bus_dmamap_unload(sc->sc_dmat, rxs->rxs_dmamap);
- if (!(rxstat & RL_RDESC_STAT_EOF)) {
- m->m_len = RE_RX_DESC_BUFLEN;
+ 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)) {
+ continue;
+ } else if (!(rxstat & RL_RDESC_STAT_EOF)) {
+ m->m_len = RL_FRAMELEN(sc->rl_max_mtu);
if (sc->rl_head == NULL)
sc->rl_head = sc->rl_tail = m;
else {
@@ -1341,24 +1352,31 @@
* 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 (rxstat & RL_RDESC_STAT_RXERRSUM && !(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;
+ }
+ continue;
}
- continue;
}
if (sc->rl_head != NULL) {
- m->m_len = total_len % RE_RX_DESC_BUFLEN;
+ m->m_len = total_len % RL_FRAMELEN(sc->rl_max_mtu);
if (m->m_len == 0)
- m->m_len = RE_RX_DESC_BUFLEN;
+ m->m_len = RL_FRAMELEN(sc->rl_max_mtu);
/*
* Special case: if there's 4 bytes or less
* in this buffer, the mbuf can be discarded:
@@ -1916,6 +1934,11 @@
htole32(*(u_int32_t *)(&eaddr.eaddr[0])));
CSR_WRITE_1(sc, RL_EECMD, RL_EEMODE_OFF);
+ if ((sc->rl_flags & RL_FLAG_JUMBOV2) != 0) {
+ ifp->if_capabilities &= ~(IFCAP_CSUM_IPv4);
+ re_set_jumbo(sc);
+ }
+
/*
* For C+ mode, initialize the RX descriptors and mbufs.
*/
@@ -1979,7 +2002,7 @@
* size so we can receive jumbo frames.
*/
if (sc->sc_hwrev != RL_HWREV_8139CPLUS) {
- if (sc->rl_flags & RL_FLAG_PCIE)
+ if (sc->rl_flags & RL_FLAG_PCIE && (sc->rl_flags &
RL_FLAG_JUMBOV2) == 0)
CSR_WRITE_2(sc, RL_MAXRXPKTLEN, RE_RX_DESC_BUFLEN);
else
CSR_WRITE_2(sc, RL_MAXRXPKTLEN, 16383);
@@ -2064,7 +2087,7 @@
break;
case SIOCGIFRXR:
error = if_rxr_ioctl((struct if_rxrinfo *)ifr->ifr_data,
- NULL, MCLBYTES, &sc->rl_ldata.rl_rx_ring);
+ NULL, RL_FRAMELEN(sc->rl_max_mtu),
&sc->rl_ldata.rl_rx_ring);
break;
default:
error = ether_ioctl(ifp, &sc->sc_arpcom, command, data);
@@ -2282,6 +2305,26 @@
panic("%s: unknown imtype %d",
sc->sc_dev.dv_xname, imtype);
}
+}
+
+void
+re_set_jumbo(struct rl_softc *sc)
+{
+ CSR_WRITE_1(sc, RL_EECMD, RL_EEMODE_WRITECFG);
+ CSR_WRITE_1(sc, RL_CFG3, CSR_READ_1(sc, RL_CFG3) |
+ RL_CFG3_JUMBO_EN0);
+ switch (sc->sc_hwrev) {
+ 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);
+ break;
+ }
+ CSR_WRITE_1(sc, RL_EECMD, RL_EEMODE_OFF);
+
}
void
Index: rtl81x9reg.h
===================================================================
RCS file: /cvs/src/sys/dev/ic/rtl81x9reg.h,v
retrieving revision 1.90
diff -u -r1.90 rtl81x9reg.h
--- rtl81x9reg.h 20 Jan 2015 04:33:06 -0000 1.90
+++ rtl81x9reg.h 21 Jan 2015 11:10:31 -0000
@@ -442,6 +442,7 @@
#define RL_CFG3_GRANTSEL 0x80
#define RL_CFG3_WOL_MAGIC 0x20
#define RL_CFG3_WOL_LINK 0x10
+#define RL_CFG3_JUMBO_EN0 0x04
#define RL_CFG3_FAST_B2B 0x01
/*
@@ -449,6 +450,7 @@
*/
#define RL_CFG4_LWPTN 0x04
#define RL_CFG4_LWPME 0x10
+#define RL_CFG4_JUMBO_EN1 0x02
/*
* Config 5 register
@@ -742,8 +744,7 @@
#define RL_ADDR_LO(y) ((u_int64_t) (y) & 0xFFFFFFFF)
#define RL_ADDR_HI(y) ((u_int64_t) (y) >> 32)
-/* see comment in dev/ic/re.c */
-#define RL_JUMBO_FRAMELEN 7440
+#define RL_JUMBO_FRAMELEN (9 * 1024)
#define RL_JUMBO_MTU_4K \
((4 * 1024) - ETHER_HDR_LEN - ETHER_CRC_LEN - ETHER_VLAN_ENCAP_LEN)
#define RL_JUMBO_MTU_6K \