diff options
| author | Marius Strobl <marius@FreeBSD.org> | 2007-01-16 20:35:23 +0000 |
|---|---|---|
| committer | Marius Strobl <marius@FreeBSD.org> | 2007-01-16 20:35:23 +0000 |
| commit | b4b958792b3523557afe174ff1b1442771c0aa31 (patch) | |
| tree | 78469cc859c31f39f7a4ec693659a0437778abbc /sys/dev/re | |
| parent | fce89853702238ca36782d9da48bac4aa4fe9039 (diff) | |
Notes
Diffstat (limited to 'sys/dev/re')
| -rw-r--r-- | sys/dev/re/if_re.c | 90 |
1 files changed, 43 insertions, 47 deletions
diff --git a/sys/dev/re/if_re.c b/sys/dev/re/if_re.c index 6eae2ac5b3ca..a4745accf6ba 100644 --- a/sys/dev/re/if_re.c +++ b/sys/dev/re/if_re.c @@ -1487,7 +1487,6 @@ re_newbuf(sc, idx, m) */ m_adj(m, RE_ETHER_ALIGN); #endif - arg.sc = sc; arg.rl_idx = idx; arg.rl_maxsegs = 1; arg.rl_flags = 0; @@ -1499,6 +1498,9 @@ re_newbuf(sc, idx, m) if (error || arg.rl_maxsegs != 1) { if (n != NULL) m_freem(n); + if (arg.rl_maxsegs == 0) + bus_dmamap_unload(sc->rl_ldata.rl_mtag, + sc->rl_ldata.rl_rx_dmamap[idx]); return (ENOMEM); } @@ -1781,13 +1783,11 @@ re_txeof(sc) idx = sc->rl_ldata.rl_tx_considx; /* Invalidate the TX descriptor list */ - bus_dmamap_sync(sc->rl_ldata.rl_tx_list_tag, sc->rl_ldata.rl_tx_list_map, BUS_DMASYNC_POSTREAD); while (sc->rl_ldata.rl_tx_free < RL_TX_DESC_CNT) { - txstat = le32toh(sc->rl_ldata.rl_tx_list[idx].rl_cmdstat); if (txstat & RL_TDESC_CMD_OWN) break; @@ -1800,7 +1800,6 @@ re_txeof(sc) * be the only place where the TX status bits * are valid. */ - if (txstat & RL_TDESC_CMD_EOF) { m_freem(sc->rl_ldata.rl_tx_mbuf[idx]); sc->rl_ldata.rl_tx_mbuf[idx] = NULL; @@ -1817,37 +1816,35 @@ re_txeof(sc) sc->rl_ldata.rl_tx_free++; RL_DESC_INC(idx); } + sc->rl_ldata.rl_tx_considx = idx; /* No changes made to the TX ring, so no flush needed */ - if (sc->rl_ldata.rl_tx_free) { - sc->rl_ldata.rl_tx_considx = idx; + if (sc->rl_ldata.rl_tx_free > RL_TX_DESC_THLD) ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - sc->rl_watchdog_timer = 0; - } - - /* - * Some chips will ignore a second TX request issued while an - * existing transmission is in progress. If the transmitter goes - * idle but there are still packets waiting to be sent, we need - * to restart the channel here to flush them out. This only seems - * to be required with the PCIe devices. - */ - if (sc->rl_ldata.rl_tx_free < RL_TX_DESC_CNT) - CSR_WRITE_1(sc, sc->rl_txstart, RL_TXSTART_START); + if (sc->rl_ldata.rl_tx_free < RL_TX_DESC_CNT) { + /* + * Some chips will ignore a second TX request issued + * while an existing transmission is in progress. If + * the transmitter goes idle but there are still + * packets waiting to be sent, we need to restart the + * channel here to flush them out. This only seems to + * be required with the PCIe devices. + */ + CSR_WRITE_1(sc, sc->rl_txstart, RL_TXSTART_START); #ifdef RE_TX_MODERATION - /* - * If not all descriptors have been released reaped yet, - * reload the timer so that we will eventually get another - * interrupt that will cause us to re-enter this routine. - * This is done in case the transmitter has gone idle. - */ - if (sc->rl_ldata.rl_tx_free != RL_TX_DESC_CNT) + /* + * If not all descriptors have been reaped yet, reload + * the timer so that we will eventually get another + * interrupt that will cause us to re-enter this routine. + * This is done in case the transmitter has gone idle. + */ CSR_WRITE_4(sc, RL_TIMERCNT, 1); #endif - + } else + sc->rl_watchdog_timer = 0; } static void @@ -2028,7 +2025,7 @@ re_encap(sc, m_head, idx) RL_LOCK_ASSERT(sc); - if (sc->rl_ldata.rl_tx_free <= 4) + if (sc->rl_ldata.rl_tx_free <= RL_TX_DESC_THLD) return (EFBIG); /* @@ -2053,11 +2050,10 @@ re_encap(sc, m_head, idx) arg.rl_flags |= RL_TDESC_CMD_UDPCSUM; } - arg.sc = sc; arg.rl_idx = *idx; arg.rl_maxsegs = sc->rl_ldata.rl_tx_free; - if (arg.rl_maxsegs > 4) - arg.rl_maxsegs -= 4; + if (arg.rl_maxsegs > RL_TX_DESC_THLD) + arg.rl_maxsegs -= RL_TX_DESC_THLD; arg.rl_ring = sc->rl_ldata.rl_tx_list; map = sc->rl_ldata.rl_tx_dmamap[*idx]; @@ -2076,7 +2072,6 @@ re_encap(sc, m_head, idx) * below can assemble the packet into a single buffer that's * padded out to the mininum frame size. */ - if (arg.rl_flags && (*m_head)->m_pkthdr.len < RL_MIN_FRAMELEN) error = EFBIG; else @@ -2091,17 +2086,20 @@ re_encap(sc, m_head, idx) /* Too many segments to map, coalesce into a single mbuf */ if (error || arg.rl_maxsegs == 0) { + if (arg.rl_maxsegs == 0) + bus_dmamap_unload(sc->rl_ldata.rl_mtag, map); m_new = m_defrag(*m_head, M_DONTWAIT); - if (m_new == NULL) + if (m_new == NULL) { + m_freem(*m_head); + *m_head = NULL; return (ENOBUFS); - else - *m_head = m_new; + } + *m_head = m_new; /* * Manually pad short frames, and zero the pad space * to avoid leaking data. */ - if (m_new->m_pkthdr.len < RL_MIN_FRAMELEN) { bzero(mtod(m_new, char *) + m_new->m_pkthdr.len, RL_MIN_FRAMELEN - m_new->m_pkthdr.len); @@ -2110,16 +2108,17 @@ re_encap(sc, m_head, idx) m_new->m_len = m_new->m_pkthdr.len; } - arg.sc = sc; - arg.rl_idx = *idx; + /* Note that we'll run over RL_TX_DESC_THLD here. */ arg.rl_maxsegs = sc->rl_ldata.rl_tx_free; - arg.rl_ring = sc->rl_ldata.rl_tx_list; - error = bus_dmamap_load_mbuf(sc->rl_ldata.rl_mtag, map, *m_head, re_dma_map_desc, &arg, BUS_DMA_NOWAIT); - if (error) { - device_printf(sc->rl_dev, "can't map mbuf (error %d)\n", - error); + if (error || arg.rl_maxsegs == 0) { + device_printf(sc->rl_dev, + "can't map defragmented mbuf (error %d)\n", error); + m_freem(m_new); + *m_head = NULL; + if (arg.rl_maxsegs == 0) + bus_dmamap_unload(sc->rl_ldata.rl_mtag, map); return (EFBIG); } } @@ -2201,6 +2200,8 @@ re_start(ifp) break; if (re_encap(sc, &m_head, &idx)) { + if (m_head == NULL) + break; IFQ_DRV_PREPEND(&ifp->if_snd, m_head); ifp->if_drv_flags |= IFF_DRV_OACTIVE; break; @@ -2232,11 +2233,6 @@ re_start(ifp) sc->rl_ldata.rl_tx_prodidx = idx; - /* - * RealTek put the TX poll request register in a different - * location on the 8169 gigE chip. I don't know why. - */ - CSR_WRITE_1(sc, sc->rl_txstart, RL_TXSTART_START); #ifdef RE_TX_MODERATION |
