summaryrefslogtreecommitdiff
path: root/sys/dev/ic/re.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/ic/re.c')
-rw-r--r--sys/dev/ic/re.c69
1 files changed, 54 insertions, 15 deletions
diff --git a/sys/dev/ic/re.c b/sys/dev/ic/re.c
index 8ad15ce2d02..a23e61502fc 100644
--- a/sys/dev/ic/re.c
+++ b/sys/dev/ic/re.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: re.c,v 1.176 2015/03/20 11:55:10 dlg Exp $ */
+/* $OpenBSD: re.c,v 1.177 2015/03/20 12:04:09 dlg Exp $ */
/* $FreeBSD: if_re.c,v 1.31 2004/09/04 07:54:05 ru Exp $ */
/*
* Copyright (c) 1997, 1998-2003
@@ -173,6 +173,8 @@ void re_watchdog(struct ifnet *);
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);
@@ -210,6 +212,10 @@ struct cfdriver re_cd = {
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;
@@ -1026,8 +1032,10 @@ re_attach(struct rl_softc *sc, const char *intrstr)
/* 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);
@@ -1042,8 +1050,7 @@ re_attach(struct rl_softc *sc, const char *intrstr)
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);
@@ -1163,7 +1170,7 @@ re_newbuf(struct rl_softc *sc)
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);
@@ -1172,7 +1179,7 @@ re_newbuf(struct rl_softc *sc)
* 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;
@@ -1311,8 +1318,12 @@ re_rxeof(struct rl_softc *sc)
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 {
@@ -1346,8 +1357,9 @@ re_rxeof(struct rl_softc *sc)
* 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)) {
+ if ((rxstat & RL_RDESC_STAT_RXERRSUM) != 0 &&
+ !(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,
@@ -1361,9 +1373,9 @@ re_rxeof(struct rl_softc *sc)
}
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:
@@ -1942,6 +1954,9 @@ re_init(struct ifnet *ifp)
htole32(*(u_int32_t *)(&eaddr.eaddr[0])));
CSR_WRITE_1(sc, RL_EECMD, RL_EEMODE_OFF);
+ if ((sc->rl_flags & RL_FLAG_JUMBOV2) != 0)
+ re_set_jumbo(sc);
+
/*
* For C+ mode, initialize the RX descriptors and mbufs.
*/
@@ -2005,7 +2020,8 @@ re_init(struct ifnet *ifp)
* 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);
@@ -2090,7 +2106,7 @@ re_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
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);
@@ -2311,6 +2327,29 @@ re_config_imtype(struct rl_softc *sc, int 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) |
+ RL_CFG4_8168E_JUMBO_EN1);
+ 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
re_setup_intr(struct rl_softc *sc, int enable_intrs, int imtype)
{
re_config_imtype(sc, imtype);