summaryrefslogtreecommitdiffstats
path: root/sys/pci
diff options
context:
space:
mode:
authorwpaul <wpaul@FreeBSD.org>1999-09-19 22:39:24 +0000
committerwpaul <wpaul@FreeBSD.org>1999-09-19 22:39:24 +0000
commit31ec4c12facbc61ce32b4ffa14d7491fd8c48f02 (patch)
tree37cfb1728c13b14ba04d57407ae9514c1ff308fd /sys/pci
parent17bce01dd1c351fc9000992083745fa44ff322d2 (diff)
downloadFreeBSD-src-31ec4c12facbc61ce32b4ffa14d7491fd8c48f02.zip
FreeBSD-src-31ec4c12facbc61ce32b4ffa14d7491fd8c48f02.tar.gz
Make some small performance tweaks to the tl driver. This should hopefully
close PR #13757, however I'm waiting on user feedback before declaring the PR officially closed. Among other things, this improves UDP transmit performance, and tx underruns are now detected and the TX start threshold adjusted accordingly.
Diffstat (limited to 'sys/pci')
-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