From owner-svn-src-all@freebsd.org Fri Apr 13 15:59:26 2018 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id A0BA3F93096; Fri, 13 Apr 2018 15:59:25 +0000 (UTC) (envelope-from br@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4E52A8371C; Fri, 13 Apr 2018 15:59:25 +0000 (UTC) (envelope-from br@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4678F1BCF5; Fri, 13 Apr 2018 15:59:25 +0000 (UTC) (envelope-from br@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id w3DFxPGv014743; Fri, 13 Apr 2018 15:59:25 GMT (envelope-from br@FreeBSD.org) Received: (from br@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id w3DFxPFl014741; Fri, 13 Apr 2018 15:59:25 GMT (envelope-from br@FreeBSD.org) Message-Id: <201804131559.w3DFxPFl014741@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: br set sender to br@FreeBSD.org using -f From: Ruslan Bukin Date: Fri, 13 Apr 2018 15:59:25 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r332474 - in head/sys: dev/altera/atse dts/mips mips/conf X-SVN-Group: head X-SVN-Commit-Author: br X-SVN-Commit-Paths: in head/sys: dev/altera/atse dts/mips mips/conf X-SVN-Commit-Revision: 332474 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.25 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 13 Apr 2018 15:59:26 -0000 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 * All rights reserved. * * This software was developed by SRI International and the University of @@ -88,29 +89,21 @@ __FBSDID("$FreeBSD$"); #include #include -#include +#include -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 -#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 ***