Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F111635302
D10557.id27883.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
5 KB
Referenced Files
None
Subscribers
None
D10557.id27883.diff
View Options
Index: sys/mips/atheros/ar531x/if_are.c
===================================================================
--- sys/mips/atheros/ar531x/if_are.c
+++ sys/mips/atheros/ar531x/if_are.c
@@ -303,8 +303,8 @@
sc->are_if_flags = ifp->if_flags;
/* XXX: add real size */
- IFQ_SET_MAXLEN(&ifp->if_snd, 9);
- ifp->if_snd.ifq_maxlen = 9;
+ IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
+ ifp->if_snd.ifq_maxlen = ifqmaxlen;
IFQ_SET_READY(&ifp->if_snd);
/* Tell the upper layer(s) we support long frames. */
@@ -686,19 +686,92 @@
{
struct are_txdesc *txd;
struct are_desc *desc, *prev_desc;
+ struct mbuf *m;
bus_dma_segment_t txsegs[ARE_MAXFRAGS];
uint32_t link_addr;
int error, i, nsegs, prod, si, prev_prod;
int txstat;
+ int startcount;
+ int padlen;
+
+ startcount = sc->are_cdata.are_tx_cnt;
ARE_LOCK_ASSERT(sc);
+ /*
+ * Some VIA Rhine wants packet buffers to be longword
+ * aligned, but very often our mbufs aren't. Rather than
+ * waste time trying to decide when to copy and when not
+ * to copy, just do it all the time.
+ */
+ m = m_defrag(*m_head, M_NOWAIT);
+ if (m == NULL) {
+ device_printf(sc->are_dev, "are_encap m_defrag error\n");
+ m_freem(*m_head);
+ *m_head = NULL;
+ return (ENOBUFS);
+ }
+ *m_head = m;
+
+ /*
+ * The Rhine chip doesn't auto-pad, so we have to make
+ * sure to pad short frames out to the minimum frame length
+ * ourselves.
+ */
+ if ((*m_head)->m_pkthdr.len < ARE_MIN_FRAMELEN) {
+ m = *m_head;
+ padlen = ARE_MIN_FRAMELEN - m->m_pkthdr.len;
+ if (M_WRITABLE(m) == 0) {
+ /* Get a writable copy. */
+ m = m_dup(*m_head, M_NOWAIT);
+ m_freem(*m_head);
+ if (m == NULL) {
+ device_printf(sc->are_dev, "are_encap m_dup error\n");
+ *m_head = NULL;
+ return (ENOBUFS);
+ }
+ *m_head = m;
+ }
+ if (m->m_next != NULL || M_TRAILINGSPACE(m) < padlen) {
+ m = m_defrag(m, M_NOWAIT);
+ if (m == NULL) {
+ device_printf(sc->are_dev, "are_encap m_defrag error\n");
+ m_freem(*m_head);
+ *m_head = NULL;
+ return (ENOBUFS);
+ }
+ }
+ /*
+ * Manually pad short frames, and zero the pad space
+ * to avoid leaking data.
+ */
+ bzero(mtod(m, char *) + m->m_pkthdr.len, padlen);
+ m->m_pkthdr.len += padlen;
+ m->m_len = m->m_pkthdr.len;
+ *m_head = m;
+ }
+
prod = sc->are_cdata.are_tx_prod;
txd = &sc->are_cdata.are_txdesc[prod];
- error = bus_dmamap_load_mbuf_sg(sc->are_cdata.are_tx_tag, txd->tx_dmamap,
- *m_head, txsegs, &nsegs, BUS_DMA_NOWAIT);
+ error = bus_dmamap_load_mbuf_sg(sc->are_cdata.are_tx_tag,
+ txd->tx_dmamap, *m_head, txsegs, &nsegs, BUS_DMA_NOWAIT);
if (error == EFBIG) {
- panic("EFBIG");
+ device_printf(sc->are_dev, "are_encap EFBIG error\n");
+ m = m_defrag(*m_head, M_NOWAIT);
+ if (m == NULL) {
+ m_freem(*m_head);
+ *m_head = NULL;
+ return (ENOBUFS);
+ }
+ *m_head = m;
+ error = bus_dmamap_load_mbuf_sg(sc->are_cdata.are_tx_tag,
+ txd->tx_dmamap, *m_head, txsegs, &nsegs, BUS_DMA_NOWAIT);
+ if (error != 0) {
+ m_freem(*m_head);
+ *m_head = NULL;
+ return (error);
+ }
+
} else if (error != 0)
return (error);
if (nsegs == 0) {
@@ -729,13 +802,12 @@
for (i = 0; i < nsegs; i++) {
desc = &sc->are_rdata.are_tx_ring[prod];
desc->are_stat = ADSTAT_OWN;
- desc->are_devcs = ARE_DMASIZE(txsegs[i].ds_len) | ADCTL_CH;
- if (i == 0)
- desc->are_devcs |= ADCTL_Tx_FS;
+ desc->are_devcs = ARE_DMASIZE(txsegs[i].ds_len);
desc->are_addr = txsegs[i].ds_addr;
/* link with previous descriptor */
- if (prev_desc)
- prev_desc->are_link = ARE_TX_RING_ADDR(sc, prod);
+ /* end of descriptor */
+ if (prod == ARE_TX_RING_CNT - 1)
+ desc->are_devcs |= ADCTL_ER;
sc->are_cdata.are_tx_cnt++;
prev_desc = desc;
@@ -761,16 +833,16 @@
/* Start transmitting */
/* Check if new list is queued in NDPTR */
txstat = (CSR_READ_4(sc, CSR_STATUS) >> 20) & 7;
- if (txstat == 0 || txstat == 6) {
- /* Transmit Process Stat is stop or suspended */
- CSR_WRITE_4(sc, CSR_TXPOLL, TXPOLL_TPD);
+ if (startcount == 0 && (txstat == 0 || txstat == 6)) {
+ desc = &sc->are_rdata.are_tx_ring[si];
+ desc->are_devcs |= ADCTL_Tx_FS;
}
else {
link_addr = ARE_TX_RING_ADDR(sc, si);
/* Get previous descriptor */
si = (si + ARE_TX_RING_CNT - 1) % ARE_TX_RING_CNT;
desc = &sc->are_rdata.are_tx_ring[si];
- desc->are_link = link_addr;
+ desc->are_devcs &= ~(ADCTL_Tx_IC | ADCTL_Tx_LS);
}
return (0);
@@ -782,6 +854,7 @@
struct are_softc *sc;
struct mbuf *m_head;
int enq;
+ int txstat;
sc = ifp->if_softc;
@@ -816,6 +889,14 @@
*/
ETHER_BPF_MTAP(ifp, m_head);
}
+
+ if (enq > 0) {
+ txstat = (CSR_READ_4(sc, CSR_STATUS) >> 20) & 7;
+ if (txstat == 0 || txstat == 6) {
+ /* Transmit Process Stat is stop or suspended */
+ CSR_WRITE_4(sc, CSR_TXPOLL, TXPOLL_TPD);
+ }
+ }
}
static void
Index: sys/mips/atheros/ar531x/if_arereg.h
===================================================================
--- sys/mips/atheros/ar531x/if_arereg.h
+++ sys/mips/atheros/ar531x/if_arereg.h
@@ -44,6 +44,8 @@
#define ARE_TX_RING_CNT 128
#define ARE_TX_RING_SIZE sizeof(struct are_desc) * ARE_TX_RING_CNT
#define ARE_RX_RING_SIZE sizeof(struct are_desc) * ARE_RX_RING_CNT
+
+#define ARE_MIN_FRAMELEN 60
#define ARE_RING_ALIGN sizeof(struct are_desc)
#define ARE_RX_ALIGN sizeof(uint32_t)
#define ARE_MAXFRAGS 8
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Mar 7, 7:59 AM (18 h, 56 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
17027927
Default Alt Text
D10557.id27883.diff (5 KB)
Attached To
Mode
D10557: fixed hi load traffic bug
Attached
Detach File
Event Timeline
Log In to Comment