summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2009-11-02 17:51:22 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2009-11-02 17:51:22 +0000
commite5d3d8658090c76c210b93df1dc79b8c3dc216c2 (patch)
tree07ccefafdb98d8248c25e1398c4752ffc5c22b1b
parent2452ea0499d5e854f0c6ccb8a0a06853177972f0 (diff)
A few fixes and improvements:
- double the number of rx buffers. - copy packets of 104 bytes or less entirely in the tx descriptor, instead of only doing this for packets smaller than an Ethernet header. - correctly disable the rx threshold interrupt. Otherwise, one received frame every 64 would not be handled because we are not using this interrupt.
-rw-r--r--sys/arch/sgi/dev/if_iec.c56
1 files changed, 29 insertions, 27 deletions
diff --git a/sys/arch/sgi/dev/if_iec.c b/sys/arch/sgi/dev/if_iec.c
index 5e7e3d2fb7a..e135d8f09b5 100644
--- a/sys/arch/sgi/dev/if_iec.c
+++ b/sys/arch/sgi/dev/if_iec.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_iec.c,v 1.1 2009/11/01 19:34:02 miod Exp $ */
+/* $OpenBSD: if_iec.c,v 1.2 2009/11/02 17:51:21 miod Exp $ */
/*
* Copyright (c) 2009 Miodrag Vallat.
@@ -162,7 +162,7 @@ struct iec_txsoft {
/*
* Receive descriptor list size.
*/
-#define IEC_NRXDESC 64
+#define IEC_NRXDESC 128
/*
* In addition to the receive descriptor themselves, we'll need an array
@@ -198,7 +198,7 @@ struct iec_control_data {
* - each rxdesc should be 128 byte aligned (this is enforced by
* struct iec_rxdesc layout).
*/
-#define IEC_CONTROL_DATA_ALIGN (16 * 1024)
+#define IEC_DMA_BOUNDARY 0x4000
#define IEC_CDOFF(x) offsetof(struct iec_control_data, x)
#define IEC_CDTXOFF(x) IEC_CDOFF(icd_txdesc[(x)])
@@ -329,7 +329,7 @@ iec_attach(struct device *parent, struct device *self, void *aux)
* by the device.
*/
rc = iec_alloc_physical(sc, &sc->sc_rxarrmap, &seg1,
- (vaddr_t *)&sc->sc_rxarr, IEC_CONTROL_DATA_ALIGN,
+ (vaddr_t *)&sc->sc_rxarr, IEC_DMA_BOUNDARY,
IEC_NRXDESC_MAX * sizeof(uint64_t), "rxdesc pointer array");
if (rc != 0)
return;
@@ -338,7 +338,7 @@ iec_attach(struct device *parent, struct device *self, void *aux)
* Allocate the RX and TX descriptors.
*/
rc = iec_alloc_physical(sc, &sc->sc_cddmamap, &seg2,
- (vaddr_t *)&sc->sc_control_data, IEC_CONTROL_DATA_ALIGN,
+ (vaddr_t *)&sc->sc_control_data, IEC_DMA_BOUNDARY,
sizeof(struct iec_control_data), "rx and tx descriptors");
if (rc != 0)
goto fail_1;
@@ -640,7 +640,7 @@ iec_init(struct ifnet *ifp)
(IEC_NRXDESC * sizeof(uint64_t)) | IOC3_ENET_PIR_SET);
/* Do not set up low water RX threshold. */
- bus_space_write_4(st, sh, IOC3_ENET_RCSR, IEC_NRXDESC);
+ bus_space_write_4(st, sh, IOC3_ENET_RCSR, 0);
/* Set up RX timer to interrupt immediately upon reception. */
bus_space_write_4(st, sh, IOC3_ENET_RTR, 0);
@@ -724,8 +724,8 @@ iec_start(struct ifnet *ifp)
bus_space_tag_t st = sc->sc_st;
bus_space_handle_t sh = sc->sc_sh;
uint64_t txdaddr;
- int error, firsttx, nexttx, opending;
- int len, txdlen;
+ int error, firstdirty, nexttx, opending;
+ int len;
if ((ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING)
return;
@@ -734,20 +734,20 @@ iec_start(struct ifnet *ifp)
* Remember the previous txpending and the first transmit descriptor.
*/
opending = sc->sc_txpending;
- firsttx = IEC_NEXTTX(sc->sc_txlast);
+ firstdirty = IEC_NEXTTX(sc->sc_txlast);
- DPRINTF(IEC_DEBUG_START,
- ("iec_start: opending = %d, firsttx = %d\n", opending, firsttx));
+ DPRINTF(IEC_DEBUG_START, ("iec_start: opending = %d, firstdirty = %d\n",
+ opending, firstdirty));
for (;;) {
- if (sc->sc_txpending == IEC_NTXDESC)
- break;
-
/* Grab a packet off the queue. */
IFQ_POLL(&ifp->if_snd, m0);
if (m0 == NULL)
break;
+ if (sc->sc_txpending == IEC_NTXDESC)
+ break;
+
/*
* Get the next available transmit descriptor.
*/
@@ -761,7 +761,7 @@ iec_start(struct ifnet *ifp)
("iec_start: len = %d, nexttx = %d\n", len, nexttx));
IFQ_DEQUEUE(&ifp->if_snd, m0);
- if (len < ETHER_PAD_LEN) {
+ if (len <= IEC_TXD_BUFSIZE) {
/*
* If the packet is small enough,
* just copy it to the buffer in txdesc and
@@ -770,12 +770,15 @@ iec_start(struct ifnet *ifp)
DPRINTF(IEC_DEBUG_START, ("iec_start: short packet\n"));
m_copydata(m0, 0, m0->m_pkthdr.len, txd->txd_buf);
- /*
- * XXX would IOC3_ENET_MCR_PADEN in MCR do this
- * XXX for us?
- */
- memset(txd->txd_buf + len, 0, ETHER_PAD_LEN - len);
- len = ETHER_PAD_LEN;
+ if (len < ETHER_PAD_LEN) {
+ /*
+ * XXX would IOC3_ENET_MCR_PADEN in MCR do this
+ * XXX for us?
+ */
+ memset(txd->txd_buf + len, 0,
+ ETHER_PAD_LEN - len);
+ len = ETHER_PAD_LEN;
+ }
txs->txs_flags = IEC_TXCMD_BUF_V;
} else {
@@ -838,11 +841,10 @@ iec_start(struct ifnet *ifp)
DPRINTF(IEC_DEBUG_START,
("iec_start: ds_addr = %p\n",
dmamap->dm_segs[0].ds_addr));
- txdlen = len;
DPRINTF(IEC_DEBUG_START,
- ("iec_start: txdaddr = %p, txdlen = %d\n",
- txdaddr, txdlen));
+ ("iec_start: txdaddr = %p, len = %d\n",
+ txdaddr, len));
/*
* Sync the DMA map for TX mbuf.
@@ -881,7 +883,6 @@ iec_start(struct ifnet *ifp)
* The chip DMA engine can not cross 16KB boundaries.
* If our mbuf doesn't fit, use the second pointer.
*/
-#define IEC_DMA_BOUNDARY 0x4000
r1 = IEC_DMA_BOUNDARY -
(txdaddr & (IEC_DMA_BOUNDARY - 1));
@@ -896,7 +897,8 @@ iec_start(struct ifnet *ifp)
if (r2 != 0) {
txs->txs_flags |= IEC_TXCMD_PTR1_V;
txd->txd_ptr[1] = txdaddr + r1;
- }
+ } else
+ txd->txd_ptr[1] = 0;
txd->txd_len = (r1 << IECTX_BUF1_LEN_SHIFT) |
(r2 << IECTX_BUF2_LEN_SHIFT);
@@ -946,7 +948,7 @@ iec_start(struct ifnet *ifp)
* reset the txdirty pointer and re-enable TX interrupt.
*/
if (opending == 0) {
- sc->sc_txdirty = firsttx;
+ sc->sc_txdirty = firstdirty;
bus_space_write_4(st, sh, IOC3_ENET_IER,
bus_space_read_4(st, sh, IOC3_ENET_IER) |
IOC3_ENET_ISR_TX_EMPTY);