svn commit: r332474 - in head/sys: dev/altera/atse dts/mips mips/conf
Ruslan Bukin
br at FreeBSD.org
Fri Apr 13 15:59:26 UTC 2018
Author: br
Date: Fri Apr 13 15:59:24 2018
New Revision: 332474
URL: https://svnweb.freebsd.org/changeset/base/332474
Log:
Convert atse(4) driver for Altera Triple-Speed Ethernet MegaCore to use
xdma(4) interface.
This allows us to switch between Altera mSGDMA or SoftDMA engines used by
atse(4) device.
This also makes atse(4) driver become 25% smaller.
Sponsored by: DARPA, AFRL
Differential Revision: https://reviews.freebsd.org/D9618
Modified:
head/sys/dev/altera/atse/if_atse.c
head/sys/dev/altera/atse/if_atse_fdt.c
head/sys/dev/altera/atse/if_atse_nexus.c
head/sys/dev/altera/atse/if_atsereg.h
head/sys/dts/mips/beripad-de4.dts
head/sys/mips/conf/BERI_DE4_BASE
Modified: head/sys/dev/altera/atse/if_atse.c
==============================================================================
--- head/sys/dev/altera/atse/if_atse.c Fri Apr 13 15:18:06 2018 (r332473)
+++ head/sys/dev/altera/atse/if_atse.c Fri Apr 13 15:59:24 2018 (r332474)
@@ -3,6 +3,7 @@
*
* Copyright (c) 2012, 2013 Bjoern A. Zeeb
* Copyright (c) 2014 Robert N. M. Watson
+ * Copyright (c) 2016-2017 Ruslan Bukin <br at bsdpad.com>
* All rights reserved.
*
* This software was developed by SRI International and the University of
@@ -88,29 +89,21 @@ __FBSDID("$FreeBSD$");
#include <dev/mii/miivar.h>
#include <dev/altera/atse/if_atsereg.h>
-#include <dev/altera/softdma/a_api.h>
+#include <dev/xdma/xdma.h>
-MODULE_DEPEND(atse, ether, 1, 1, 1);
-MODULE_DEPEND(atse, miibus, 1, 1, 1);
+#define RX_QUEUE_SIZE 4096
+#define TX_QUEUE_SIZE 4096
+#define NUM_RX_MBUF 512
+#define BUFRING_SIZE 8192
+#include <machine/cache.h>
-#define ATSE_WATCHDOG_TIME 5
-
-#ifdef DEVICE_POLLING
-static poll_handler_t atse_poll;
-#endif
-
/* XXX once we'd do parallel attach, we need a global lock for this. */
#define ATSE_ETHERNET_OPTION_BITS_UNDEF 0
#define ATSE_ETHERNET_OPTION_BITS_READ 1
static int atse_ethernet_option_bits_flag = ATSE_ETHERNET_OPTION_BITS_UNDEF;
static uint8_t atse_ethernet_option_bits[ALTERA_ETHERNET_OPTION_BITS_LEN];
-static int atse_intr_debug_enable = 0;
-SYSCTL_INT(_debug, OID_AUTO, atse_intr_debug_enable, CTLFLAG_RW,
- &atse_intr_debug_enable, 0,
- "Extra debugging output for atse interrupts");
-
/*
* Softc and critical resource locking.
*/
@@ -118,155 +111,15 @@ SYSCTL_INT(_debug, OID_AUTO, atse_intr_debug_enable, C
#define ATSE_UNLOCK(_sc) mtx_unlock(&(_sc)->atse_mtx)
#define ATSE_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->atse_mtx, MA_OWNED)
-#define ATSE_TX_PENDING(sc) (sc->atse_tx_m != NULL || \
- !IFQ_DRV_IS_EMPTY(&ifp->if_snd))
+#define ATSE_DEBUG
+#undef ATSE_DEBUG
-#ifdef DEBUG
+#ifdef ATSE_DEBUG
#define DPRINTF(format, ...) printf(format, __VA_ARGS__)
#else
#define DPRINTF(format, ...)
#endif
-/* a_api.c functions; factor out? */
-static inline void
-a_onchip_fifo_mem_core_write(struct resource *res, uint32_t off,
- uint32_t val4, const char *desc, const char *f, const int l)
-{
-
- val4 = htole32(val4);
- DPRINTF("[%s:%d] FIFOW %s 0x%08x = 0x%08x\n", f, l, desc, off, val4);
- bus_write_4(res, off, val4);
-}
-
-static inline uint32_t
-a_onchip_fifo_mem_core_read(struct resource *res, uint32_t off,
- const char *desc, const char *f, const int l)
-{
- uint32_t val4;
-
- val4 = le32toh(bus_read_4(res, off));
- DPRINTF("[%s:%d] FIFOR %s 0x%08x = 0x%08x\n", f, l, desc, off, val4);
-
- return (val4);
-}
-
-/* The FIFO does an endian conversion, so we must not do it as well. */
-/* XXX-BZ in fact we should do a htobe32 so le would be fine as well? */
-#define ATSE_TX_DATA_WRITE(sc, val4) \
- bus_write_4((sc)->atse_tx_mem_res, A_ONCHIP_FIFO_MEM_CORE_DATA, val4)
-
-#define ATSE_TX_META_WRITE(sc, val4) \
- a_onchip_fifo_mem_core_write((sc)->atse_tx_mem_res, \
- A_ONCHIP_FIFO_MEM_CORE_METADATA, \
- (val4), "TXM", __func__, __LINE__)
-#define ATSE_TX_META_READ(sc) \
- a_onchip_fifo_mem_core_read((sc)->atse_tx_mem_res, \
- A_ONCHIP_FIFO_MEM_CORE_METADATA, \
- "TXM", __func__, __LINE__)
-
-#define ATSE_TX_READ_FILL_LEVEL(sc) \
- a_onchip_fifo_mem_core_read((sc)->atse_txc_mem_res, \
- A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_FILL_LEVEL, \
- "TX_FILL", __func__, __LINE__)
-#define ATSE_RX_READ_FILL_LEVEL(sc) \
- a_onchip_fifo_mem_core_read((sc)->atse_rxc_mem_res, \
- A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_FILL_LEVEL, \
- "RX_FILL", __func__, __LINE__)
-
-/* The FIFO does an endian conversion, so we must not do it as well. */
-/* XXX-BZ in fact we should do a htobe32 so le would be fine as well? */
-#define ATSE_RX_DATA_READ(sc) \
- bus_read_4((sc)->atse_rx_mem_res, A_ONCHIP_FIFO_MEM_CORE_DATA)
-#define ATSE_RX_META_READ(sc) \
- a_onchip_fifo_mem_core_read((sc)->atse_rx_mem_res, \
- A_ONCHIP_FIFO_MEM_CORE_METADATA, \
- "RXM", __func__, __LINE__)
-
-#define ATSE_RX_STATUS_READ(sc) \
- a_onchip_fifo_mem_core_read((sc)->atse_rxc_mem_res, \
- A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_I_STATUS, \
- "RX_EVENT", __func__, __LINE__)
-
-#define ATSE_TX_STATUS_READ(sc) \
- a_onchip_fifo_mem_core_read((sc)->atse_txc_mem_res, \
- A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_I_STATUS, \
- "TX_EVENT", __func__, __LINE__)
-
-#define ATSE_RX_EVENT_READ(sc) \
- a_onchip_fifo_mem_core_read((sc)->atse_rxc_mem_res, \
- A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_EVENT, \
- "RX_EVENT", __func__, __LINE__)
-
-#define ATSE_TX_EVENT_READ(sc) \
- a_onchip_fifo_mem_core_read((sc)->atse_txc_mem_res, \
- A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_EVENT, \
- "TX_EVENT", __func__, __LINE__)
-
-#define ATSE_RX_EVENT_CLEAR(sc) \
- do { \
- uint32_t val4; \
- \
- val4 = a_onchip_fifo_mem_core_read( \
- (sc)->atse_rxc_mem_res, \
- A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_EVENT, \
- "RX_EVENT", __func__, __LINE__); \
- if (val4 != 0x00) \
- a_onchip_fifo_mem_core_write( \
- (sc)->atse_rxc_mem_res, \
- A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_EVENT, \
- val4, "RX_EVENT", __func__, __LINE__); \
- } while(0)
-#define ATSE_TX_EVENT_CLEAR(sc) \
- do { \
- uint32_t val4; \
- \
- val4 = a_onchip_fifo_mem_core_read( \
- (sc)->atse_txc_mem_res, \
- A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_EVENT, \
- "TX_EVENT", __func__, __LINE__); \
- if (val4 != 0x00) \
- a_onchip_fifo_mem_core_write( \
- (sc)->atse_txc_mem_res, \
- A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_EVENT, \
- val4, "TX_EVENT", __func__, __LINE__); \
- } while(0)
-
-#define ATSE_RX_EVENTS (A_ONCHIP_FIFO_MEM_CORE_INTR_FULL | \
- A_ONCHIP_FIFO_MEM_CORE_INTR_OVERFLOW | \
- A_ONCHIP_FIFO_MEM_CORE_INTR_UNDERFLOW)
-#define ATSE_RX_INTR_ENABLE(sc) \
- a_onchip_fifo_mem_core_write((sc)->atse_rxc_mem_res, \
- A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_INT_ENABLE, \
- ATSE_RX_EVENTS, \
- "RX_INTR", __func__, __LINE__) /* XXX-BZ review later. */
-#define ATSE_RX_INTR_DISABLE(sc) \
- a_onchip_fifo_mem_core_write((sc)->atse_rxc_mem_res, \
- A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_INT_ENABLE, 0, \
- "RX_INTR", __func__, __LINE__)
-#define ATSE_RX_INTR_READ(sc) \
- a_onchip_fifo_mem_core_read((sc)->atse_rxc_mem_res, \
- A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_INT_ENABLE, \
- "RX_INTR", __func__, __LINE__)
-
-#define ATSE_TX_EVENTS (A_ONCHIP_FIFO_MEM_CORE_INTR_EMPTY | \
- A_ONCHIP_FIFO_MEM_CORE_INTR_OVERFLOW | \
- A_ONCHIP_FIFO_MEM_CORE_INTR_UNDERFLOW)
-#define ATSE_TX_INTR_ENABLE(sc) \
- a_onchip_fifo_mem_core_write((sc)->atse_txc_mem_res, \
- A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_INT_ENABLE, \
- ATSE_TX_EVENTS, \
- "TX_INTR", __func__, __LINE__) /* XXX-BZ review later. */
-#define ATSE_TX_INTR_DISABLE(sc) \
- a_onchip_fifo_mem_core_write((sc)->atse_txc_mem_res, \
- A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_INT_ENABLE, 0, \
- "TX_INTR", __func__, __LINE__)
-#define ATSE_TX_INTR_READ(sc) \
- a_onchip_fifo_mem_core_read((sc)->atse_txc_mem_res, \
- A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_INT_ENABLE, \
- "TX_INTR", __func__, __LINE__)
-
-static int atse_rx_locked(struct atse_softc *sc);
-
/*
* Register space access macros.
*/
@@ -345,146 +198,194 @@ static int atse_detach(device_t);
devclass_t atse_devclass;
static int
-atse_tx_locked(struct atse_softc *sc, int *sent)
+atse_rx_enqueue(struct atse_softc *sc, uint32_t n)
{
struct mbuf *m;
- uint32_t val4, fill_level;
- int leftm;
- int c;
+ int i;
- ATSE_LOCK_ASSERT(sc);
+ for (i = 0; i < n; i++) {
+ m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
+ if (m == NULL) {
+ device_printf(sc->dev,
+ "%s: Can't alloc rx mbuf\n", __func__);
+ return (-1);
+ }
- m = sc->atse_tx_m;
- KASSERT(m != NULL, ("%s: m is null: sc=%p", __func__, sc));
- KASSERT(m->m_flags & M_PKTHDR, ("%s: not a pkthdr: m=%p", __func__, m));
-
- /*
- * Copy to buffer to minimize our pain as we can only store
- * double words which, after the first mbuf gets out of alignment
- * quite quickly.
- */
- if (sc->atse_tx_m_offset == 0) {
- m_copydata(m, 0, m->m_pkthdr.len, sc->atse_tx_buf);
- sc->atse_tx_buf_len = m->m_pkthdr.len;
+ m->m_pkthdr.len = m->m_len = m->m_ext.ext_size;
+ xdma_enqueue_mbuf(sc->xchan_rx, &m, 0, 4, 4, XDMA_DEV_TO_MEM);
}
- fill_level = ATSE_TX_READ_FILL_LEVEL(sc);
-#if 0 /* Returns 0xdeadc0de. */
- val4 = ATSE_TX_META_READ(sc);
-#endif
- if (sc->atse_tx_m_offset == 0) {
- /* Write start of packet. */
- val4 = A_ONCHIP_FIFO_MEM_CORE_SOP;
- val4 &= ~A_ONCHIP_FIFO_MEM_CORE_EOP;
- ATSE_TX_META_WRITE(sc, val4);
+ return (0);
+}
+
+static int
+atse_xdma_tx_intr(void *arg, xdma_transfer_status_t *status)
+{
+ xdma_transfer_status_t st;
+ struct atse_softc *sc;
+ struct ifnet *ifp;
+ struct mbuf *m;
+ int err;
+
+ sc = arg;
+
+ ATSE_LOCK(sc);
+
+ ifp = sc->atse_ifp;
+
+ for (;;) {
+ err = xdma_dequeue_mbuf(sc->xchan_tx, &m, &st);
+ if (err != 0) {
+ break;
+ }
+
+ if (st.error != 0) {
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ }
+
+ m_freem(m);
+ sc->txcount--;
}
- /* TX FIFO is single clock mode, so we have the full FIFO. */
- c = 0;
- while ((sc->atse_tx_buf_len - sc->atse_tx_m_offset) > 4 &&
- fill_level < AVALON_FIFO_TX_BASIC_OPTS_DEPTH) {
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- bcopy(&sc->atse_tx_buf[sc->atse_tx_m_offset], &val4,
- sizeof(val4));
- ATSE_TX_DATA_WRITE(sc, val4);
- sc->atse_tx_m_offset += sizeof(val4);
- c += sizeof(val4);
+ ATSE_UNLOCK(sc);
- fill_level++;
- if (fill_level == AVALON_FIFO_TX_BASIC_OPTS_DEPTH)
- fill_level = ATSE_TX_READ_FILL_LEVEL(sc);
+ return (0);
+}
+
+static int
+atse_xdma_rx_intr(void *arg, xdma_transfer_status_t *status)
+{
+ xdma_transfer_status_t st;
+ struct atse_softc *sc;
+ struct ifnet *ifp;
+ struct mbuf *m;
+ int err;
+ uint32_t cnt_processed;
+
+ sc = arg;
+
+ ATSE_LOCK(sc);
+
+ ifp = sc->atse_ifp;
+
+ cnt_processed = 0;
+ for (;;) {
+ err = xdma_dequeue_mbuf(sc->xchan_rx, &m, &st);
+ if (err != 0) {
+ break;
+ }
+ cnt_processed++;
+
+ if (st.error != 0) {
+ if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ m_freem(m);
+ continue;
+ }
+
+ m->m_pkthdr.len = m->m_len = st.transferred;
+ m->m_pkthdr.rcvif = ifp;
+ m_adj(m, ETHER_ALIGN);
+ ATSE_UNLOCK(sc);
+ (*ifp->if_input)(ifp, m);
+ ATSE_LOCK(sc);
}
- if (sent != NULL)
- *sent += c;
- /* Set EOP *before* writing the last symbol. */
- if (sc->atse_tx_m_offset >= (sc->atse_tx_buf_len - 4) &&
- fill_level < AVALON_FIFO_TX_BASIC_OPTS_DEPTH) {
+ atse_rx_enqueue(sc, cnt_processed);
- /* Set EndOfPacket. */
- val4 = A_ONCHIP_FIFO_MEM_CORE_EOP;
+ ATSE_UNLOCK(sc);
- /* Set EMPTY. */
- leftm = sc->atse_tx_buf_len - sc->atse_tx_m_offset;
- val4 |= ((4 - leftm) << A_ONCHIP_FIFO_MEM_CORE_EMPTY_SHIFT);
- ATSE_TX_META_WRITE(sc, val4);
+ return (0);
+}
- /* Write last symbol. */
- val4 = 0;
- bcopy(sc->atse_tx_buf + sc->atse_tx_m_offset, &val4, leftm);
- ATSE_TX_DATA_WRITE(sc, val4);
+static int
+atse_transmit_locked(struct ifnet *ifp)
+{
+ struct atse_softc *sc;
+ struct mbuf *m;
+ struct buf_ring *br;
+ int error;
+ int enq;
- if (sent != NULL)
- *sent += leftm;
+ sc = ifp->if_softc;
+ br = sc->br;
- /* OK, the packet is gone. */
- sc->atse_tx_m = NULL;
- sc->atse_tx_m_offset = 0;
+ enq = 0;
+ while ((m = drbr_peek(ifp, br)) != NULL) {
+ error = xdma_enqueue_mbuf(sc->xchan_tx, &m, 0, 4, 4, XDMA_MEM_TO_DEV);
+ if (error != 0) {
+ /* No space in request queue available yet. */
+ drbr_putback(ifp, br, m);
+ break;
+ }
+
+ drbr_advance(ifp, br);
+
+ sc->txcount++;
+ enq++;
+
/* If anyone is interested give them a copy. */
- BPF_MTAP(sc->atse_ifp, m);
+ ETHER_BPF_MTAP(ifp, m);
+ }
- m_freem(m);
- return (0);
- }
+ if (enq > 0)
+ xdma_queue_submit(sc->xchan_tx);
- return (EBUSY);
+ return (0);
}
-static void
-atse_start_locked(struct ifnet *ifp)
+static int
+atse_transmit(struct ifnet *ifp, struct mbuf *m)
{
struct atse_softc *sc;
- int error, sent;
+ struct buf_ring *br;
+ int error;
sc = ifp->if_softc;
- ATSE_LOCK_ASSERT(sc);
+ br = sc->br;
- if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) !=
- IFF_DRV_RUNNING || (sc->atse_flags & ATSE_FLAGS_LINK) == 0)
- return;
+ ATSE_LOCK(sc);
-#if 1
- /*
- * Disable the watchdog while sending, we are batching packets.
- * Though we should never reach 5 seconds, and are holding the lock,
- * but who knows.
- */
- sc->atse_watchdog_timer = 0;
-#endif
+ mtx_lock(&sc->br_mtx);
- if (sc->atse_tx_m != NULL) {
- error = atse_tx_locked(sc, &sent);
- if (error != 0)
- goto done;
+ if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != IFF_DRV_RUNNING) {
+ error = drbr_enqueue(ifp, sc->br, m);
+ mtx_unlock(&sc->br_mtx);
+ ATSE_UNLOCK(sc);
+ return (error);
}
- /* We have more space to send so continue ... */
- for (; !IFQ_DRV_IS_EMPTY(&ifp->if_snd); ) {
- IFQ_DRV_DEQUEUE(&ifp->if_snd, sc->atse_tx_m);
- sc->atse_tx_m_offset = 0;
- if (sc->atse_tx_m == NULL)
- break;
- error = atse_tx_locked(sc, &sent);
- if (error != 0)
- goto done;
+ if ((sc->atse_flags & ATSE_FLAGS_LINK) == 0) {
+ error = drbr_enqueue(ifp, sc->br, m);
+ mtx_unlock(&sc->br_mtx);
+ ATSE_UNLOCK(sc);
+ return (error);
}
-done:
- /* If the IP core walks into Nekromanteion try to bail out. */
- if (sent > 0)
- sc->atse_watchdog_timer = ATSE_WATCHDOG_TIME;
+ error = drbr_enqueue(ifp, br, m);
+ if (error) {
+ mtx_unlock(&sc->br_mtx);
+ ATSE_UNLOCK(sc);
+ return (error);
+ }
+ error = atse_transmit_locked(ifp);
+
+ mtx_unlock(&sc->br_mtx);
+ ATSE_UNLOCK(sc);
+
+ return (error);
}
static void
-atse_start(struct ifnet *ifp)
+atse_qflush(struct ifnet *ifp)
{
struct atse_softc *sc;
sc = ifp->if_softc;
- ATSE_LOCK(sc);
- atse_start_locked(ifp);
- ATSE_UNLOCK(sc);
+
+ printf("%s\n", __func__);
}
static int
@@ -496,36 +397,33 @@ atse_stop_locked(struct atse_softc *sc)
ATSE_LOCK_ASSERT(sc);
- sc->atse_watchdog_timer = 0;
callout_stop(&sc->atse_tick);
ifp = sc->atse_ifp;
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
- ATSE_RX_INTR_DISABLE(sc);
- ATSE_TX_INTR_DISABLE(sc);
- ATSE_RX_EVENT_CLEAR(sc);
- ATSE_TX_EVENT_CLEAR(sc);
/* Disable MAC transmit and receive datapath. */
mask = BASE_CFG_COMMAND_CONFIG_TX_ENA|BASE_CFG_COMMAND_CONFIG_RX_ENA;
val4 = CSR_READ_4(sc, BASE_CFG_COMMAND_CONFIG);
val4 &= ~mask;
CSR_WRITE_4(sc, BASE_CFG_COMMAND_CONFIG, val4);
+
/* Wait for bits to be cleared; i=100 is excessive. */
for (i = 0; i < 100; i++) {
val4 = CSR_READ_4(sc, BASE_CFG_COMMAND_CONFIG);
- if ((val4 & mask) == 0)
+ if ((val4 & mask) == 0) {
break;
+ }
DELAY(10);
}
- if ((val4 & mask) != 0)
+
+ if ((val4 & mask) != 0) {
device_printf(sc->atse_dev, "Disabling MAC TX/RX timed out.\n");
/* Punt. */
+ }
sc->atse_flags &= ~ATSE_FLAGS_LINK;
- /* XXX-BZ free the RX/TX rings. */
-
return (0);
}
@@ -561,10 +459,11 @@ atse_rxfilter_locked(struct atse_softc *sc)
val4 &= ~BASE_CFG_COMMAND_CONFIG_MHASH_SEL;
ifp = sc->atse_ifp;
- if (ifp->if_flags & IFF_PROMISC)
+ if (ifp->if_flags & IFF_PROMISC) {
val4 |= BASE_CFG_COMMAND_CONFIG_PROMIS_EN;
- else
+ } else {
val4 &= ~BASE_CFG_COMMAND_CONFIG_PROMIS_EN;
+ }
CSR_WRITE_4(sc, BASE_CFG_COMMAND_CONFIG, val4);
@@ -587,16 +486,18 @@ atse_rxfilter_locked(struct atse_softc *sc)
*/
if_maddr_rlock(ifp);
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
+ if (ifma->ifma_addr->sa_family != AF_LINK) {
continue;
+ }
h |= (1 << atse_mchash(sc,
LLADDR((struct sockaddr_dl *)ifma->ifma_addr)));
}
if_maddr_runlock(ifp);
- for (i = 0; i <= MHASH_LEN; i++)
+ for (i = 0; i <= MHASH_LEN; i++) {
CSR_WRITE_4(sc, MHASH_START + i,
(h & (1 << i)) ? 0x01 : 0x00);
+ }
}
return (0);
@@ -609,22 +510,26 @@ atse_ethernet_option_bits_read_fdt(device_t dev)
device_t fdev;
int i, rid;
- if (atse_ethernet_option_bits_flag & ATSE_ETHERNET_OPTION_BITS_READ)
+ if (atse_ethernet_option_bits_flag & ATSE_ETHERNET_OPTION_BITS_READ) {
return (0);
+ }
fdev = device_find_child(device_get_parent(dev), "cfi", 0);
- if (fdev == NULL)
+ if (fdev == NULL) {
return (ENOENT);
+ }
rid = 0;
res = bus_alloc_resource_any(fdev, SYS_RES_MEMORY, &rid,
RF_ACTIVE | RF_SHAREABLE);
- if (res == NULL)
+ if (res == NULL) {
return (ENXIO);
+ }
- for (i = 0; i < ALTERA_ETHERNET_OPTION_BITS_LEN; i++)
+ for (i = 0; i < ALTERA_ETHERNET_OPTION_BITS_LEN; i++) {
atse_ethernet_option_bits[i] = bus_read_1(res,
ALTERA_ETHERNET_OPTION_BITS_OFF + i);
+ }
bus_release_resource(fdev, SYS_RES_MEMORY, rid, res);
atse_ethernet_option_bits_flag |= ATSE_ETHERNET_OPTION_BITS_READ;
@@ -658,12 +563,14 @@ atse_get_eth_address(struct atse_softc *sc)
* possibly change our ethernet address, which is not good at all.
*/
if (sc->atse_eth_addr[0] != 0x00 || sc->atse_eth_addr[1] != 0x00 ||
- sc->atse_eth_addr[2] != 0x00)
+ sc->atse_eth_addr[2] != 0x00) {
return (0);
+ }
if ((atse_ethernet_option_bits_flag &
- ATSE_ETHERNET_OPTION_BITS_READ) == 0)
+ ATSE_ETHERNET_OPTION_BITS_READ) == 0) {
goto get_random;
+ }
val4 = atse_ethernet_option_bits[0] << 24;
val4 |= atse_ethernet_option_bits[1] << 16;
@@ -718,8 +625,9 @@ atse_get_eth_address(struct atse_softc *sc)
* Ethernet, go to random.
*/
unit = device_get_unit(sc->atse_dev);
- if (unit == 0x00)
+ if (unit == 0x00) {
return (0);
+ }
if (unit > 0x0f) {
device_printf(sc->atse_dev, "We do not support Ethernet "
@@ -831,8 +739,9 @@ atse_reset(struct atse_softc *sc)
/* Wait for reset bit to clear; i=100 is excessive. */
for (i = 0; i < 100; i++) {
val = PCS_READ_2(sc, PCS_CONTROL);
- if ((val & PCS_CONTROL_RESET) == 0)
+ if ((val & PCS_CONTROL_RESET) == 0) {
break;
+ }
DELAY(10);
}
@@ -851,8 +760,9 @@ atse_reset(struct atse_softc *sc)
/* Wait for bits to be cleared; i=100 is excessive. */
for (i = 0; i < 100; i++) {
val4 = CSR_READ_4(sc, BASE_CFG_COMMAND_CONFIG);
- if ((val4 & mask) == 0)
+ if ((val4 & mask) == 0) {
break;
+ }
DELAY(10);
}
if ((val4 & mask) != 0) {
@@ -926,8 +836,10 @@ atse_reset(struct atse_softc *sc)
val4 = CSR_READ_4(sc, TX_CMD_STAT);
val4 &= ~(TX_CMD_STAT_OMIT_CRC|TX_CMD_STAT_TX_SHIFT16);
CSR_WRITE_4(sc, TX_CMD_STAT, val4);
+
val4 = CSR_READ_4(sc, RX_CMD_STAT);
val4 &= ~RX_CMD_STAT_RX_SHIFT16;
+ val4 |= RX_CMD_STAT_RX_SHIFT16;
CSR_WRITE_4(sc, RX_CMD_STAT, val4);
/* e. Reset MAC. */
@@ -937,8 +849,9 @@ atse_reset(struct atse_softc *sc)
/* Wait for bits to be cleared; i=100 is excessive. */
for (i = 0; i < 100; i++) {
val4 = CSR_READ_4(sc, BASE_CFG_COMMAND_CONFIG);
- if ((val4 & BASE_CFG_COMMAND_CONFIG_SW_RESET) == 0)
+ if ((val4 & BASE_CFG_COMMAND_CONFIG_SW_RESET) == 0) {
break;
+ }
DELAY(10);
}
if ((val4 & BASE_CFG_COMMAND_CONFIG_SW_RESET) != 0) {
@@ -954,8 +867,9 @@ atse_reset(struct atse_softc *sc)
/* Wait for bits to be cleared; i=100 is excessive. */
for (i = 0; i < 100; i++) {
val4 = CSR_READ_4(sc, BASE_CFG_COMMAND_CONFIG);
- if ((val4 & mask) == mask)
+ if ((val4 & mask) == mask) {
break;
+ }
DELAY(10);
}
if ((val4 & mask) != mask) {
@@ -976,8 +890,9 @@ atse_init_locked(struct atse_softc *sc)
ATSE_LOCK_ASSERT(sc);
ifp = sc->atse_ifp;
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) {
return;
+ }
/*
* Must update the ether address if changed. Given we do not handle
@@ -989,31 +904,14 @@ atse_init_locked(struct atse_softc *sc)
/* Make things frind to halt, cleanup, ... */
atse_stop_locked(sc);
- /* ... reset, ... */
+
atse_reset(sc);
/* ... and fire up the engine again. */
atse_rxfilter_locked(sc);
- /* Memory rings? DMA engine? */
-
- sc->atse_rx_buf_len = 0;
sc->atse_flags &= ATSE_FLAGS_LINK; /* Preserve. */
-#ifdef DEVICE_POLLING
- /* Only enable interrupts if we are not polling. */
- if (ifp->if_capenable & IFCAP_POLLING) {
- ATSE_RX_INTR_DISABLE(sc);
- ATSE_TX_INTR_DISABLE(sc);
- ATSE_RX_EVENT_CLEAR(sc);
- ATSE_TX_EVENT_CLEAR(sc);
- } else
-#endif
- {
- ATSE_RX_INTR_ENABLE(sc);
- ATSE_TX_INTR_ENABLE(sc);
- }
-
mii = device_get_softc(sc->atse_miibus);
sc->atse_flags &= ~ATSE_FLAGS_LINK;
@@ -1070,39 +968,6 @@ atse_ioctl(struct ifnet *ifp, u_long command, caddr_t
case SIOCSIFCAP:
ATSE_LOCK(sc);
mask = ifr->ifr_reqcap ^ ifp->if_capenable;
-#ifdef DEVICE_POLLING
- if ((mask & IFCAP_POLLING) != 0 &&
- (IFCAP_POLLING & ifp->if_capabilities) != 0) {
- ifp->if_capenable ^= IFCAP_POLLING;
- if ((IFCAP_POLLING & ifp->if_capenable) != 0) {
-
- error = ether_poll_register(atse_poll, ifp);
- if (error != 0) {
- ATSE_UNLOCK(sc);
- break;
- }
- /* Disable interrupts. */
- ATSE_RX_INTR_DISABLE(sc);
- ATSE_TX_INTR_DISABLE(sc);
- ATSE_RX_EVENT_CLEAR(sc);
- ATSE_TX_EVENT_CLEAR(sc);
-
- /*
- * Do not allow disabling of polling if we do
- * not have interrupts.
- */
- } else if (sc->atse_rx_irq_res != NULL ||
- sc->atse_tx_irq_res != NULL) {
- error = ether_poll_deregister(ifp);
- /* Enable interrupts. */
- ATSE_RX_INTR_ENABLE(sc);
- ATSE_TX_INTR_ENABLE(sc);
- } else {
- ifp->if_capenable ^= IFCAP_POLLING;
- error = EINVAL;
- }
- }
-#endif /* DEVICE_POLLING */
ATSE_UNLOCK(sc);
break;
case SIOCADDMULTI:
@@ -1131,55 +996,6 @@ atse_ioctl(struct ifnet *ifp, u_long command, caddr_t
}
static void
-atse_intr_debug(struct atse_softc *sc, const char *intrname)
-{
- uint32_t rxs, rxe, rxi, rxf, txs, txe, txi, txf;
-
- if (!atse_intr_debug_enable)
- return;
-
- rxs = ATSE_RX_STATUS_READ(sc);
- rxe = ATSE_RX_EVENT_READ(sc);
- rxi = ATSE_RX_INTR_READ(sc);
- rxf = ATSE_RX_READ_FILL_LEVEL(sc);
-
- txs = ATSE_TX_STATUS_READ(sc);
- txe = ATSE_TX_EVENT_READ(sc);
- txi = ATSE_TX_INTR_READ(sc);
- txf = ATSE_TX_READ_FILL_LEVEL(sc);
-
- printf(
- "%s - %s: "
- "rxs 0x%x rxe 0x%x rxi 0x%x rxf 0x%x "
- "txs 0x%x txe 0x%x txi 0x%x txf 0x%x\n",
- __func__, intrname,
- rxs, rxe, rxi, rxf,
- txs, txe, txi, txf);
-}
-
-static void
-atse_watchdog(struct atse_softc *sc)
-{
-
- ATSE_LOCK_ASSERT(sc);
-
- if (sc->atse_watchdog_timer == 0 || --sc->atse_watchdog_timer > 0)
- return;
-
- device_printf(sc->atse_dev, "watchdog timeout\n");
- if_inc_counter(sc->atse_ifp, IFCOUNTER_OERRORS, 1);
-
- atse_intr_debug(sc, "poll");
-
- sc->atse_ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
- atse_init_locked(sc);
-
- atse_rx_locked(sc);
- if (!IFQ_DRV_IS_EMPTY(&sc->atse_ifp->if_snd))
- atse_start_locked(sc->atse_ifp);
-}
-
-static void
atse_tick(void *xsc)
{
struct atse_softc *sc;
@@ -1192,9 +1008,10 @@ atse_tick(void *xsc)
mii = device_get_softc(sc->atse_miibus);
mii_tick(mii);
- atse_watchdog(sc);
- if ((sc->atse_flags & ATSE_FLAGS_LINK) == 0)
+ if ((sc->atse_flags & ATSE_FLAGS_LINK) == 0) {
atse_miibus_statchg(sc->atse_dev);
+ }
+
callout_reset(&sc->atse_tick, hz, atse_tick, sc);
}
@@ -1213,171 +1030,15 @@ atse_ifmedia_upd(struct ifnet *ifp)
ATSE_LOCK(sc);
mii = device_get_softc(sc->atse_miibus);
- LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
+ LIST_FOREACH(miisc, &mii->mii_phys, mii_list) {
PHY_RESET(miisc);
+ }
error = mii_mediachg(mii);
ATSE_UNLOCK(sc);
return (error);
}
-static void
-atse_update_rx_err(struct atse_softc *sc, uint32_t mask)
-{
- int i;
-
- /* RX error are 6 bits, we only know 4 of them. */
- for (i = 0; i < ATSE_RX_ERR_MAX; i++)
- if ((mask & (1 << i)) != 0)
- sc->atse_rx_err[i]++;
-}
-
-static int
-atse_rx_locked(struct atse_softc *sc)
-{
- uint32_t fill, i, j;
- uint32_t data, meta;
- struct ifnet *ifp;
- struct mbuf *m;
- int rx_npkts;
-
- ATSE_LOCK_ASSERT(sc);
-
- ifp = sc->atse_ifp;
- rx_npkts = 0;
- j = 0;
- meta = 0;
- do {
-outer:
- if (sc->atse_rx_m == NULL) {
- m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
- if (m == NULL)
- return (rx_npkts);
- m->m_len = m->m_pkthdr.len = MCLBYTES;
- /* Make sure upper layers will be aligned. */
- m_adj(m, ETHER_ALIGN);
- sc->atse_rx_m = m;
- }
-
- fill = ATSE_RX_READ_FILL_LEVEL(sc);
- for (i = 0; i < fill; i++) {
- /*
- * XXX-BZ for whatever reason the FIFO requires the
- * the data read before we can access the meta data.
- */
- data = ATSE_RX_DATA_READ(sc);
- meta = ATSE_RX_META_READ(sc);
- if (meta & A_ONCHIP_FIFO_MEM_CORE_ERROR_MASK) {
- /* XXX-BZ evaluate error. */
- atse_update_rx_err(sc, ((meta &
- A_ONCHIP_FIFO_MEM_CORE_ERROR_MASK) >>
- A_ONCHIP_FIFO_MEM_CORE_ERROR_SHIFT) & 0xff);
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
- sc->atse_rx_buf_len = 0;
- /*
- * Should still read till EOP or next SOP.
- *
- * XXX-BZ might also depend on
- * BASE_CFG_COMMAND_CONFIG_RX_ERR_DISC
- */
- sc->atse_flags |= ATSE_FLAGS_ERROR;
- return (rx_npkts);
- }
- if ((meta & A_ONCHIP_FIFO_MEM_CORE_CHANNEL_MASK) != 0)
- device_printf(sc->atse_dev, "%s: unexpected "
- "channel %u\n", __func__, (meta &
- A_ONCHIP_FIFO_MEM_CORE_CHANNEL_MASK) >>
- A_ONCHIP_FIFO_MEM_CORE_CHANNEL_SHIFT);
-
- if (meta & A_ONCHIP_FIFO_MEM_CORE_SOP) {
- /*
- * There is no need to clear SOP between 1st
- * and subsequent packet data junks.
- */
- if (sc->atse_rx_buf_len != 0 &&
- (sc->atse_flags & ATSE_FLAGS_SOP_SEEN) == 0)
- {
- device_printf(sc->atse_dev, "%s: SOP "
- "without empty buffer: %u\n",
- __func__, sc->atse_rx_buf_len);
- /* XXX-BZ any better counter? */
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
- }
-
- if ((sc->atse_flags & ATSE_FLAGS_SOP_SEEN) == 0)
- {
- sc->atse_flags |= ATSE_FLAGS_SOP_SEEN;
- sc->atse_rx_buf_len = 0;
- }
- }
-#if 0 /* We had to read the data before we could access meta data. See above. */
- data = ATSE_RX_DATA_READ(sc);
-#endif
- /* Make sure to not overflow the mbuf data size. */
- if (sc->atse_rx_buf_len >= sc->atse_rx_m->m_len -
- sizeof(data)) {
- /*
- * XXX-BZ Error. We need more mbufs and are
- * not setup for this yet.
- */
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
- sc->atse_flags |= ATSE_FLAGS_ERROR;
- }
- if ((sc->atse_flags & ATSE_FLAGS_ERROR) == 0)
- /*
- * MUST keep this bcopy as m_data after m_adj
- * for IP header aligment is on half-word
- * and not word alignment.
- */
- bcopy(&data, (uint8_t *)(sc->atse_rx_m->m_data +
- sc->atse_rx_buf_len), sizeof(data));
- if (meta & A_ONCHIP_FIFO_MEM_CORE_EOP) {
- uint8_t empty;
-
- empty = (meta &
- A_ONCHIP_FIFO_MEM_CORE_EMPTY_MASK) >>
- A_ONCHIP_FIFO_MEM_CORE_EMPTY_SHIFT;
- sc->atse_rx_buf_len += (4 - empty);
-
- if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
- rx_npkts++;
-
- m = sc->atse_rx_m;
- m->m_pkthdr.len = m->m_len =
- sc->atse_rx_buf_len;
- sc->atse_rx_m = NULL;
-
- sc->atse_rx_buf_len = 0;
- sc->atse_flags &= ~ATSE_FLAGS_SOP_SEEN;
- if (sc->atse_flags & ATSE_FLAGS_ERROR) {
- sc->atse_flags &= ~ATSE_FLAGS_ERROR;
- m_freem(m);
- } else {
- m->m_pkthdr.rcvif = ifp;
- ATSE_UNLOCK(sc);
- (*ifp->if_input)(ifp, m);
- ATSE_LOCK(sc);
- }
-#ifdef DEVICE_POLLING
- if (ifp->if_capenable & IFCAP_POLLING) {
- if (sc->atse_rx_cycles <= 0)
- return (rx_npkts);
- sc->atse_rx_cycles--;
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-head
mailing list