summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/pci/if_tl.c69
-rw-r--r--sys/pci/if_tlreg.h33
2 files changed, 60 insertions, 42 deletions
diff --git a/sys/pci/if_tl.c b/sys/pci/if_tl.c
index b642e93..ed43a81 100644
--- a/sys/pci/if_tl.c
+++ b/sys/pci/if_tl.c
@@ -1058,9 +1058,6 @@ static void tl_softreset(sc, internal)
if (sc->tl_bitrate)
tl_dio_setbit16(sc, TL_NETCONFIG, TL_CFG_BITRATE);
- /* Set PCI burst size */
- tl_dio_write8(sc, TL_BSIZEREG, 0x33);
-
/*
* Load adapter irq pacing timer and tx threshold.
* We make the transmit threshold 1 initially but we may
@@ -1116,8 +1113,6 @@ static int tl_attach(dev)
struct tl_type *t;
struct ifnet *ifp;
struct tl_softc *sc;
- unsigned int round;
- caddr_t roundptr;
int unit, error = 0, rid;
s = splimp();
@@ -1229,21 +1224,12 @@ static int tl_attach(dev)
}
/*
- * Now allocate memory for the TX and RX lists. Note that
- * we actually allocate 8 bytes more than we really need:
- * this is because we need to adjust the final address to
- * be aligned on a quadword (64-bit) boundary in order to
- * make the chip happy. If the list structures aren't properly
- * aligned, DMA fails and the chip generates an adapter check
- * interrupt and has to be reset. If you set up the softc struct
- * just right you can sort of obtain proper alignment 'by chance.'
- * But I don't want to depend on this, so instead the alignment
- * is forced here.
+ * Now allocate memory for the TX and RX lists.
*/
- sc->tl_ldata_ptr = malloc(sizeof(struct tl_list_data) + 8,
- M_DEVBUF, M_NOWAIT);
+ sc->tl_ldata = contigmalloc(sizeof(struct tl_list_data), M_DEVBUF,
+ M_NOWAIT, 0x100000, 0xffffffff, PAGE_SIZE, 0);
- if (sc->tl_ldata_ptr == NULL) {
+ if (sc->tl_ldata == NULL) {
bus_teardown_intr(dev, sc->tl_irq, sc->tl_intrhand);
bus_release_resource(dev, SYS_RES_IRQ, 0, sc->tl_irq);
bus_release_resource(dev, TL_RES, TL_RID, sc->tl_res);
@@ -1252,23 +1238,6 @@ static int tl_attach(dev)
goto fail;
}
- /*
- * Convoluted but satisfies my ANSI sensibilities. GCC lets
- * you do casts on the LHS of an assignment, but ANSI doesn't
- * allow that.
- */
- sc->tl_ldata = (struct tl_list_data *)sc->tl_ldata_ptr;
- round = (uintptr_t)sc->tl_ldata_ptr & 0xF;
- roundptr = sc->tl_ldata_ptr;
- for (i = 0; i < 8; i++) {
- if (round % 8) {
- round++;
- roundptr++;
- } else
- break;
- }
- sc->tl_ldata = (struct tl_list_data *)roundptr;
-
bzero(sc->tl_ldata, sizeof(struct tl_list_data));
sc->tl_unit = unit;
@@ -1291,7 +1260,8 @@ static int tl_attach(dev)
bus_teardown_intr(dev, sc->tl_irq, sc->tl_intrhand);
bus_release_resource(dev, SYS_RES_IRQ, 0, sc->tl_irq);
bus_release_resource(dev, TL_RES, TL_RID, sc->tl_res);
- free(sc->tl_ldata_ptr, M_DEVBUF);
+ contigfree(sc->tl_ldata,
+ sizeof(struct tl_list_data), M_DEVBUF);
printf("tl%d: failed to read station address\n", unit);
error = ENXIO;
goto fail;
@@ -1336,7 +1306,7 @@ static int tl_attach(dev)
ifp->if_watchdog = tl_watchdog;
ifp->if_init = tl_init;
ifp->if_mtu = ETHERMTU;
- ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
+ ifp->if_snd.ifq_maxlen = TL_TX_LIST_CNT - 1;
callout_handle_init(&sc->tl_stat_ch);
/* Reset the adapter again. */
@@ -1399,7 +1369,7 @@ static int tl_detach(dev)
bus_generic_detach(dev);
device_delete_child(dev, sc->tl_miibus);
- free(sc->tl_ldata_ptr, M_DEVBUF);
+ contigfree(sc->tl_ldata, sizeof(struct tl_list_data), M_DEVBUF);
if (sc->tl_bitrate)
ifmedia_removeall(&sc->ifmedia);
@@ -1713,7 +1683,7 @@ static int tl_intvec_txeoc(xsc, type)
CMD_PUT(sc, TL_CMD_ACK | 0x00000001 | type);
/* Then load the address of the next TX list. */
CSR_WRITE_4(sc, TL_CH_PARM,
- vtophys(sc->tl_cdata.tl_tx_head->tl_ptr));
+ vtophys(sc->tl_cdata.tl_tx_head->tl_ptr));
/* Restart TX channel. */
cmd = CSR_READ_4(sc, TL_HOSTCMD);
cmd &= ~TL_CMD_RT;
@@ -1868,6 +1838,20 @@ static void tl_stats_update(xsc)
tl_rx_overrun(tl_stats);
ifp->if_oerrors += tl_tx_underrun(tl_stats);
+ if (tl_tx_underrun(tl_stats)) {
+ u_int8_t tx_thresh;
+ tx_thresh = tl_dio_read8(sc, TL_ACOMMIT) & TL_AC_TXTHRESH;
+ if (tx_thresh != TL_AC_TXTHRESH_WHOLEPKT) {
+ tx_thresh >>= 4;
+ tx_thresh++;
+ printf("tl%d: tx underrun -- increasing "
+ "tx threshold to %d bytes\n", sc->tl_unit,
+ (64 * (tx_thresh * 4)));
+ tl_dio_clrbit(sc, TL_ACOMMIT, TL_AC_TXTHRESH);
+ tl_dio_setbit(sc, TL_ACOMMIT, tx_thresh << 4);
+ }
+ }
+
sc->tl_stat_ch = timeout(tl_stats_update, sc, hz);
if (!sc->tl_bitrate) {
@@ -2088,6 +2072,13 @@ static void tl_init(xsc)
*/
tl_stop(sc);
+ /* Initialize TX FIFO threshold */
+ tl_dio_clrbit(sc, TL_ACOMMIT, TL_AC_TXTHRESH);
+ tl_dio_setbit(sc, TL_ACOMMIT, TL_AC_TXTHRESH_16LONG);
+
+ /* Set PCI burst size */
+ tl_dio_write8(sc, TL_BSIZEREG, TL_RXBURST_16LONG|TL_TXBURST_16LONG);
+
/*
* Set 'capture all frames' bit for promiscuous mode.
*/
diff --git a/sys/pci/if_tlreg.h b/sys/pci/if_tlreg.h
index b06f5e9..29c7e62 100644
--- a/sys/pci/if_tlreg.h
+++ b/sys/pci/if_tlreg.h
@@ -49,8 +49,8 @@ struct tl_type {
*/
#define TL_MAXFRAGS 10
-#define TL_RX_LIST_CNT 20
-#define TL_TX_LIST_CNT 20
+#define TL_RX_LIST_CNT 64
+#define TL_TX_LIST_CNT 128
#define TL_MIN_FRAMELEN 64
struct tl_frag {
@@ -120,7 +120,6 @@ struct tl_softc {
struct tl_type *tl_dinfo; /* ThunderLAN adapter info */
u_int8_t tl_unit; /* interface number */
u_int8_t tl_eeaddr;
- caddr_t tl_ldata_ptr;
struct tl_list_data *tl_ldata; /* TX/RX lists and mbufs */
struct tl_chain_data tl_cdata;
u_int8_t tl_txeoc;
@@ -458,6 +457,34 @@ struct tl_stats {
#define TL_AC_MTXD2 0x04 /* loopback disable */
#define TL_AC_MTXD3 0x08 /* full duplex disable */
+#define TL_AC_TXTHRESH 0xF0
+#define TL_AC_TXTHRESH_16LONG 0x00
+#define TL_AC_TXTHRESH_32LONG 0x10
+#define TL_AC_TXTHRESH_64LONG 0x20
+#define TL_AC_TXTHRESH_128LONG 0x30
+#define TL_AC_TXTHRESH_256LONG 0x40
+#define TL_AC_TXTHRESH_WHOLEPKT 0x50
+
+/*
+ * PCI burst size register (TL_BSIZEREG).
+ */
+#define TL_RXBURST 0x0F
+#define TL_TXBURST 0xF0
+
+#define TL_RXBURST_4LONG 0x00
+#define TL_RXBURST_8LONG 0x01
+#define TL_RXBURST_16LONG 0x02
+#define TL_RXBURST_32LONG 0x03
+#define TL_RXBURST_64LONG 0x04
+#define TL_RXBURST_128LONG 0x05
+
+#define TL_TXBURST_4LONG 0x00
+#define TL_TXBURST_8LONG 0x10
+#define TL_TXBURST_16LONG 0x20
+#define TL_TXBURST_32LONG 0x30
+#define TL_TXBURST_64LONG 0x40
+#define TL_TXBURST_128LONG 0x50
+
/*
* register space access macros
*/
OpenPOWER on IntegriCloud