diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/pci/if_tl.c | 69 | ||||
-rw-r--r-- | sys/pci/if_tlreg.h | 33 |
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 */ |