Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/ic Bring back support for enhanced descriptor format...
details: https://anonhg.NetBSD.org/src/rev/6a0f0390bdb6
branches: trunk
changeset: 836292:6a0f0390bdb6
user: martin <martin%NetBSD.org@localhost>
date: Mon Oct 08 17:09:31 2018 +0000
description:
Bring back support for enhanced descriptor format in newer core versions.
Fix a few endian bugs and check the main core version before trying to
read the hardware feature mask. Only read the hardware feature register
if core version reported is >= 3.5 (all my older hardware reports 0).
With some hints and patches from jared, and ok from aymeric
diffstat:
sys/dev/ic/dwc_gmac.c | 271 ++++++++++++++++++++++++++++++++++++++-------
sys/dev/ic/dwc_gmac_reg.h | 30 ++++-
sys/dev/ic/dwc_gmac_var.h | 19 +++-
3 files changed, 273 insertions(+), 47 deletions(-)
diffs (truncated from 549 to 300 lines):
diff -r 26ccb82fcfb1 -r 6a0f0390bdb6 sys/dev/ic/dwc_gmac.c
--- a/sys/dev/ic/dwc_gmac.c Mon Oct 08 16:31:35 2018 +0000
+++ b/sys/dev/ic/dwc_gmac.c Mon Oct 08 17:09:31 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: dwc_gmac.c,v 1.54 2018/09/28 21:51:42 aymeric Exp $ */
+/* $NetBSD: dwc_gmac.c,v 1.55 2018/10/08 17:09:31 martin Exp $ */
/*-
* Copyright (c) 2013, 2014 The NetBSD Foundation, Inc.
@@ -41,7 +41,7 @@
#include <sys/cdefs.h>
-__KERNEL_RCSID(1, "$NetBSD: dwc_gmac.c,v 1.54 2018/09/28 21:51:42 aymeric Exp $");
+__KERNEL_RCSID(1, "$NetBSD: dwc_gmac.c,v 1.55 2018/10/08 17:09:31 martin Exp $");
/* #define DWC_GMAC_DEBUG 1 */
@@ -100,6 +100,53 @@
static void dwc_gmac_setmulti(struct dwc_gmac_softc *sc);
static int dwc_gmac_ifflags_cb(struct ethercom *);
static uint32_t bitrev32(uint32_t x);
+static void dwc_gmac_desc_set_owned_by_dev(struct dwc_gmac_dev_dmadesc *);
+static int dwc_gmac_desc_is_owned_by_dev(struct dwc_gmac_dev_dmadesc *);
+static void dwc_gmac_desc_std_set_len(struct dwc_gmac_dev_dmadesc *, int);
+static uint32_t dwc_gmac_desc_std_get_len(struct dwc_gmac_dev_dmadesc *);
+static void dwc_gmac_desc_std_tx_init_flags(struct dwc_gmac_dev_dmadesc *);
+static void dwc_gmac_desc_std_tx_set_first_frag(struct dwc_gmac_dev_dmadesc *);
+static void dwc_gmac_desc_std_tx_set_last_frag(struct dwc_gmac_dev_dmadesc *);
+static void dwc_gmac_desc_std_rx_init_flags(struct dwc_gmac_dev_dmadesc *);
+static int dwc_gmac_desc_std_rx_has_error(struct dwc_gmac_dev_dmadesc *);
+static void dwc_gmac_desc_enh_set_len(struct dwc_gmac_dev_dmadesc *, int);
+static uint32_t dwc_gmac_desc_enh_get_len(struct dwc_gmac_dev_dmadesc *);
+static void dwc_gmac_desc_enh_tx_init_flags(struct dwc_gmac_dev_dmadesc *);
+static void dwc_gmac_desc_enh_tx_set_first_frag(struct dwc_gmac_dev_dmadesc *);
+static void dwc_gmac_desc_enh_tx_set_last_frag(struct dwc_gmac_dev_dmadesc *);
+static void dwc_gmac_desc_enh_rx_init_flags(struct dwc_gmac_dev_dmadesc *);
+static int dwc_gmac_desc_enh_rx_has_error(struct dwc_gmac_dev_dmadesc *);
+
+static const struct dwc_gmac_desc_methods desc_methods_standard = {
+ .tx_init_flags = dwc_gmac_desc_std_tx_init_flags,
+ .tx_set_owned_by_dev = dwc_gmac_desc_set_owned_by_dev,
+ .tx_is_owned_by_dev = dwc_gmac_desc_is_owned_by_dev,
+ .tx_set_len = dwc_gmac_desc_std_set_len,
+ .tx_set_first_frag = dwc_gmac_desc_std_tx_set_first_frag,
+ .tx_set_last_frag = dwc_gmac_desc_std_tx_set_last_frag,
+ .rx_init_flags = dwc_gmac_desc_std_rx_init_flags,
+ .rx_set_owned_by_dev = dwc_gmac_desc_set_owned_by_dev,
+ .rx_is_owned_by_dev = dwc_gmac_desc_is_owned_by_dev,
+ .rx_set_len = dwc_gmac_desc_std_set_len,
+ .rx_get_len = dwc_gmac_desc_std_get_len,
+ .rx_has_error = dwc_gmac_desc_std_rx_has_error
+};
+
+static const struct dwc_gmac_desc_methods desc_methods_enhanced = {
+ .tx_init_flags = dwc_gmac_desc_enh_tx_init_flags,
+ .tx_set_owned_by_dev = dwc_gmac_desc_set_owned_by_dev,
+ .tx_is_owned_by_dev = dwc_gmac_desc_is_owned_by_dev,
+ .tx_set_len = dwc_gmac_desc_enh_set_len,
+ .tx_set_first_frag = dwc_gmac_desc_enh_tx_set_first_frag,
+ .tx_set_last_frag = dwc_gmac_desc_enh_tx_set_last_frag,
+ .rx_init_flags = dwc_gmac_desc_enh_rx_init_flags,
+ .rx_set_owned_by_dev = dwc_gmac_desc_set_owned_by_dev,
+ .rx_is_owned_by_dev = dwc_gmac_desc_is_owned_by_dev,
+ .rx_set_len = dwc_gmac_desc_enh_set_len,
+ .rx_get_len = dwc_gmac_desc_enh_get_len,
+ .rx_has_error = dwc_gmac_desc_enh_rx_has_error
+};
+
#define TX_DESC_OFFSET(N) ((AWGE_RX_RING_COUNT+(N)) \
*sizeof(struct dwc_gmac_dev_dmadesc))
@@ -122,7 +169,7 @@
#define AWIN_DEF_MAC_INTRMASK \
(AWIN_GMAC_MAC_INT_TSI | AWIN_GMAC_MAC_INT_ANEG | \
- AWIN_GMAC_MAC_INT_LINKCHG | AWIN_GMAC_MAC_INT_RGSMII)
+ AWIN_GMAC_MAC_INT_LINKCHG)
#ifdef DWC_GMAC_DEBUG
static void dwc_gmac_dump_dma(struct dwc_gmac_softc *sc);
@@ -141,7 +188,7 @@
dwc_gmac_attach(struct dwc_gmac_softc *sc, uint32_t mii_clk)
{
uint8_t enaddr[ETHER_ADDR_LEN];
- uint32_t maclo, machi;
+ uint32_t maclo, machi, ver, hwft;
struct mii_data * const mii = &sc->sc_mii;
struct ifnet * const ifp = &sc->sc_ec.ec_if;
prop_dictionary_t dict;
@@ -185,6 +232,9 @@
enaddr[5] = (machi >> 8) & 0x0ff;
}
+ ver = bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_VERSION);
+ aprint_normal_dev(sc->sc_dev, "Core version: %08x\n", ver);
+
/*
* Init chip and do initial setup
*/
@@ -194,6 +244,21 @@
aprint_normal_dev(sc->sc_dev, "Ethernet address %s\n",
ether_sprintf(enaddr));
+ hwft = 0;
+ if (ver >= 0x35) {
+ hwft = bus_space_read_4(sc->sc_bst, sc->sc_bsh,
+ AWIN_GMAC_DMA_HWFEATURES);
+ aprint_normal_dev(sc->sc_dev,
+ "HW feature mask: %x\n", hwft);
+ }
+ if (hwft & GMAC_DMA_FEAT_ENHANCED_DESC) {
+ aprint_normal_dev(sc->sc_dev,
+ "Using enhanced descriptor format\n");
+ sc->sc_descm = &desc_methods_enhanced;
+ } else {
+ sc->sc_descm = &desc_methods_standard;
+ }
+
/*
* Allocate Tx and Rx rings
*/
@@ -444,10 +509,9 @@
next = RX_NEXT(i);
desc->ddesc_next = htole32(ring->r_physaddr
+ next * sizeof(*desc));
- desc->ddesc_cntl = htole32(
- __SHIFTIN(AWGE_MAX_PACKET,DDESC_CNTL_SIZE1MASK) |
- DDESC_CNTL_RXCHAIN);
- desc->ddesc_status = htole32(DDESC_STATUS_OWNEDBYDEV);
+ sc->sc_descm->rx_init_flags(desc);
+ sc->sc_descm->rx_set_len(desc, AWGE_MAX_PACKET);
+ sc->sc_descm->rx_set_owned_by_dev(desc);
}
bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_ring_map, 0,
@@ -473,10 +537,9 @@
mutex_enter(&ring->r_mtx);
for (i = 0; i < AWGE_RX_RING_COUNT; i++) {
desc = &sc->sc_rxq.r_desc[i];
- desc->ddesc_cntl = htole32(
- __SHIFTIN(AWGE_MAX_PACKET,DDESC_CNTL_SIZE1MASK) |
- DDESC_CNTL_RXCHAIN);
- desc->ddesc_status = htole32(DDESC_STATUS_OWNEDBYDEV);
+ sc->sc_descm->rx_init_flags(desc);
+ sc->sc_descm->rx_set_len(desc, AWGE_MAX_PACKET);
+ sc->sc_descm->rx_set_owned_by_dev(desc);
}
bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_ring_map, 0,
@@ -891,11 +954,11 @@
dwc_gmac_txdesc_sync(sc, start, sc->sc_txq.t_cur,
BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
- bus_space_write_4(sc->sc_bst, sc->sc_bsh,
- AWIN_GMAC_DMA_TXPOLL, ~0U);
#ifdef DWC_GMAC_DEBUG
dwc_dump_status(sc);
#endif
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh,
+ AWIN_GMAC_DMA_TXPOLL, ~0U);
}
}
@@ -942,7 +1005,6 @@
struct dwc_gmac_dev_dmadesc *desc = NULL;
struct dwc_gmac_tx_data *data = NULL;
bus_dmamap_t map;
- uint32_t flags, len, status;
int error, i, first;
#ifdef DWC_GMAC_DEBUG
@@ -966,38 +1028,37 @@
return ENOBUFS;
}
- flags = DDESC_CNTL_TXFIRST|DDESC_CNTL_TXCHAIN;
- status = 0;
for (i = 0; i < map->dm_nsegs; i++) {
data = &sc->sc_txq.t_data[sc->sc_txq.t_cur];
desc = &sc->sc_txq.t_desc[sc->sc_txq.t_cur];
desc->ddesc_data = htole32(map->dm_segs[i].ds_addr);
- len = __SHIFTIN(map->dm_segs[i].ds_len, DDESC_CNTL_SIZE1MASK);
#ifdef DWC_GMAC_DEBUG
aprint_normal_dev(sc->sc_dev, "enqueing desc #%d data %08lx "
- "len %lu (flags: %08x, len: %08x)\n", sc->sc_txq.t_cur,
+ "len %lu\n", sc->sc_txq.t_cur,
(unsigned long)map->dm_segs[i].ds_addr,
- (unsigned long)map->dm_segs[i].ds_len,
- flags, len);
+ (unsigned long)map->dm_segs[i].ds_len);
#endif
- desc->ddesc_cntl = htole32(len|flags);
- flags &= ~DDESC_CNTL_TXFIRST;
+ sc->sc_descm->tx_init_flags(desc);
+ sc->sc_descm->tx_set_len(desc, map->dm_segs[i].ds_len);
+
+ if (i == 0)
+ sc->sc_descm->tx_set_first_frag(desc);
/*
* Defer passing ownership of the first descriptor
* until we are done.
*/
- desc->ddesc_status = htole32(status);
- status |= DDESC_STATUS_OWNEDBYDEV;
+ if (i != 0)
+ sc->sc_descm->tx_set_owned_by_dev(desc);
sc->sc_txq.t_queued++;
sc->sc_txq.t_cur = TX_NEXT(sc->sc_txq.t_cur);
}
- desc->ddesc_cntl |= htole32(DDESC_CNTL_TXLAST|DDESC_CNTL_TXINT);
+ sc->sc_descm->tx_set_last_frag(desc);
data->td_m = m0;
data->td_active = map;
@@ -1006,8 +1067,10 @@
BUS_DMASYNC_PREWRITE);
/* Pass first to device */
- sc->sc_txq.t_desc[first].ddesc_status =
- htole32(DDESC_STATUS_OWNEDBYDEV);
+ sc->sc_descm->tx_set_owned_by_dev(&sc->sc_txq.t_desc[first]);
+
+ bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
+ BUS_DMASYNC_PREWRITE);
return 0;
}
@@ -1087,7 +1150,6 @@
struct ifnet *ifp = &sc->sc_ec.ec_if;
struct dwc_gmac_tx_data *data;
struct dwc_gmac_dev_dmadesc *desc;
- uint32_t status;
int i, nsegs;
mutex_enter(&sc->sc_txq.t_mtx);
@@ -1108,8 +1170,7 @@
BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
desc = &sc->sc_txq.t_desc[i];
- status = le32toh(desc->ddesc_status);
- if (status & DDESC_STATUS_OWNEDBYDEV)
+ if (sc->sc_descm->tx_is_owned_by_dev(desc))
break;
data = &sc->sc_txq.t_data[i];
@@ -1149,7 +1210,6 @@
struct dwc_gmac_dev_dmadesc *desc;
struct dwc_gmac_rx_data *data;
bus_addr_t physaddr;
- uint32_t status;
struct mbuf *m, *mnew;
int i, len, error;
@@ -1161,21 +1221,20 @@
desc = &sc->sc_rxq.r_desc[i];
data = &sc->sc_rxq.r_data[i];
- status = le32toh(desc->ddesc_status);
- if (status & DDESC_STATUS_OWNEDBYDEV)
+ if (sc->sc_descm->rx_is_owned_by_dev(desc))
break;
- if (status & (DDESC_STATUS_RXERROR|DDESC_STATUS_RXTRUNCATED)) {
+ if (sc->sc_descm->rx_has_error(desc)) {
#ifdef DWC_GMAC_DEBUG
aprint_normal_dev(sc->sc_dev,
"RX error: descriptor status %08x, skipping\n",
- status);
+ le32toh(desc->ddesc_status0));
#endif
ifp->if_ierrors++;
goto skip;
}
- len = __SHIFTOUT(status, DDESC_STATUS_FRMLENMSK);
+ len = sc->sc_descm->rx_get_len(desc);
#ifdef DWC_GMAC_DEBUG
aprint_normal_dev(sc->sc_dev,
@@ -1241,10 +1300,11 @@
skip:
bus_dmamap_sync(sc->sc_dmat, data->rd_map, 0,
data->rd_map->dm_mapsize, BUS_DMASYNC_PREREAD);
- desc->ddesc_cntl = htole32(
- __SHIFTIN(AWGE_MAX_PACKET,DDESC_CNTL_SIZE1MASK) |
- DDESC_CNTL_RXCHAIN);
- desc->ddesc_status = htole32(DDESC_STATUS_OWNEDBYDEV);
+
+ sc->sc_descm->rx_init_flags(desc);
+ sc->sc_descm->rx_set_len(desc, AWGE_MAX_PACKET);
+ sc->sc_descm->rx_set_owned_by_dev(desc);
+
bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_ring_map,
Home |
Main Index |
Thread Index |
Old Index