diff options
Diffstat (limited to 'sys/dev/neta/if_mvnetavar.h')
-rw-r--r-- | sys/dev/neta/if_mvnetavar.h | 327 |
1 files changed, 327 insertions, 0 deletions
diff --git a/sys/dev/neta/if_mvnetavar.h b/sys/dev/neta/if_mvnetavar.h new file mode 100644 index 0000000..912e9d7 --- /dev/null +++ b/sys/dev/neta/if_mvnetavar.h @@ -0,0 +1,327 @@ +/* + * Copyright (c) 2017 Stormshield. + * Copyright (c) 2017 Semihalf. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + * + */ + +#ifndef _IF_MVNETAVAR_H_ +#define _IF_MVNETAVAR_H_ +#include <net/if.h> + +#define MVNETA_HWHEADER_SIZE 2 /* Marvell Header */ +#define MVNETA_ETHER_SIZE 22 /* Maximum ether size */ +#define MVNETA_MAX_CSUM_MTU 1600 /* Port1,2 hw limit */ + +/* + * Limit support for frame up to hw csum limit + * until jumbo frame support is added. + */ +#define MVNETA_MAX_FRAME (MVNETA_MAX_CSUM_MTU + MVNETA_ETHER_SIZE) + +/* + * Default limit of queue length + * + * queue 0 is lowest priority and queue 7 is highest priority. + * IP packet is received on queue 7 by default. + */ +#define MVNETA_TX_RING_CNT 512 +#define MVNETA_RX_RING_CNT 256 + +#define MVNETA_BUFRING_SIZE 1024 + +#define MVNETA_PACKET_OFFSET 64 +#define MVNETA_PACKET_SIZE MCLBYTES + +#define MVNETA_RXTH_COUNT 128 +#define MVNETA_RX_REFILL_COUNT 8 +#define MVNETA_TX_RECLAIM_COUNT 32 + +/* + * Device Register access + */ +#define MVNETA_READ(sc, reg) \ + bus_read_4((sc)->res[0], (reg)) +#define MVNETA_WRITE(sc, reg, val) \ + bus_write_4((sc)->res[0], (reg), (val)) + +#define MVNETA_READ_REGION(sc, reg, val, c) \ + bus_read_region_4((sc)->res[0], (reg), (val), (c)) +#define MVNETA_WRITE_REGION(sc, reg, val, c) \ + bus_write_region_4((sc)->res[0], (reg), (val), (c)) + +#define MVNETA_READ_MIB_4(sc, reg) \ + bus_read_4((sc)->res[0], MVNETA_PORTMIB_BASE + (reg)) +#define MVNETA_READ_MIB_8(sc, reg) \ + bus_read_8((sc)->res[0], MVNETA_PORTMIB_BASE + (reg)) + +#define MVNETA_IS_LINKUP(sc) \ + (MVNETA_READ((sc), MVNETA_PSR) & MVNETA_PSR_LINKUP) + +#define MVNETA_IS_QUEUE_SET(queues, q) \ + ((((queues) >> (q)) & 0x1)) + +/* + * EEE: Lower Power Idle config + * Default timer is duration of MTU sized frame transmission. + * The timer can be negotiated by LLDP protocol, but we have no + * support. + */ +#define MVNETA_LPI_TS (ETHERMTU * 8 / 1000) /* [us] */ +#define MVNETA_LPI_TW (ETHERMTU * 8 / 1000) /* [us] */ +#define MVNETA_LPI_LI (ETHERMTU * 8 / 1000) /* [us] */ + +/* + * DMA Descriptor + * + * the ethernet device has 8 rx/tx DMA queues. each of queue has its own + * decriptor list. descriptors are simply index by counter inside the device. + */ +#define MVNETA_TX_SEGLIMIT 32 + +#define MVNETA_QUEUE_IDLE 1 +#define MVNETA_QUEUE_WORKING 2 +#define MVNETA_QUEUE_DISABLED 3 + +struct mvneta_buf { + struct mbuf * m; /* pointer to related mbuf */ + bus_dmamap_t dmap; +}; + +struct mvneta_rx_ring { + int queue_status; + /* Real descriptors array. shared by RxDMA */ + struct mvneta_rx_desc *desc; + bus_dmamap_t desc_map; + bus_addr_t desc_pa; + + /* Managment entries for each of descritors */ + struct mvneta_buf rxbuf[MVNETA_RX_RING_CNT]; + + /* locks */ + struct mtx ring_mtx; + + /* Index */ + int dma; + int cpu; + + /* Limit */ + int queue_th_received; + int queue_th_time; /* [Tclk] */ + + /* LRO */ + struct lro_ctrl lro; + boolean_t lro_enabled; + /* Is this queue out of mbuf */ + boolean_t needs_refill; +} __aligned(CACHE_LINE_SIZE); + +struct mvneta_tx_ring { + /* Index of this queue */ + int qidx; + /* IFNET pointer */ + struct ifnet *ifp; + /* Ring buffer for IFNET */ + struct buf_ring *br; + /* Real descriptors array. shared by TxDMA */ + struct mvneta_tx_desc *desc; + bus_dmamap_t desc_map; + bus_addr_t desc_pa; + + /* Managment entries for each of descritors */ + struct mvneta_buf txbuf[MVNETA_TX_RING_CNT]; + + /* locks */ + struct mtx ring_mtx; + + /* Index */ + int used; + int dma; + int cpu; + + /* watchdog */ +#define MVNETA_WATCHDOG_TXCOMP (hz / 10) /* 100ms */ +#define MVNETA_WATCHDOG (10 * hz) /* 10s */ + int watchdog_time; + int queue_status; + boolean_t queue_hung; + + /* Task */ + struct task task; + struct taskqueue *taskq; + + /* Stats */ + uint32_t drv_error; +} __aligned(CACHE_LINE_SIZE); + +static __inline int +tx_counter_adv(int ctr, int n) +{ + + ctr += n; + while (__predict_false(ctr >= MVNETA_TX_RING_CNT)) + ctr -= MVNETA_TX_RING_CNT; + + return (ctr); +} + +static __inline int +rx_counter_adv(int ctr, int n) +{ + + ctr += n; + while (__predict_false(ctr >= MVNETA_RX_RING_CNT)) + ctr -= MVNETA_RX_RING_CNT; + + return (ctr); +} + +/* + * Timeout control + */ +#define MVNETA_PHY_TIMEOUT 10000 /* msec */ +#define RX_DISABLE_TIMEOUT 0x1000000 /* times */ +#define TX_DISABLE_TIMEOUT 0x1000000 /* times */ +#define TX_FIFO_EMPTY_TIMEOUT 0x1000000 /* times */ + +/* + * Debug + */ +#define KASSERT_SC_MTX(sc) \ + KASSERT(mtx_owned(&(sc)->mtx), ("SC mutex not owned")) +#define KASSERT_BM_MTX(sc) \ + KASSERT(mtx_owned(&(sc)->bm.bm_mtx), ("BM mutex not owned")) +#define KASSERT_RX_MTX(sc, q) \ + KASSERT(mtx_owned(&(sc)->rx_ring[(q)].ring_mtx),\ + ("RX mutex not owned")) +#define KASSERT_TX_MTX(sc, q) \ + KASSERT(mtx_owned(&(sc)->tx_ring[(q)].ring_mtx),\ + ("TX mutex not owned")) + +/* + * sysctl(9) parameters + */ +struct mvneta_sysctl_queue { + struct mvneta_softc *sc; + int rxtx; + int queue; +}; +#define MVNETA_SYSCTL_RX 0 +#define MVNETA_SYSCTL_TX 1 + +struct mvneta_sysctl_mib { + struct mvneta_softc *sc; + int index; + uint64_t counter; +}; + +enum mvneta_phy_mode { + MVNETA_PHY_QSGMII, + MVNETA_PHY_SGMII, + MVNETA_PHY_RGMII, + MVNETA_PHY_RGMII_ID +}; + +/* + * Ethernet Device main context + */ +DECLARE_CLASS(mvneta_driver); + +struct mvneta_softc { + device_t dev; + uint32_t version; + /* + * mtx must be held by interface functions to/from + * other frameworks. interrupt hander, sysctl hander, + * ioctl hander, and so on. + */ + struct mtx mtx; + struct resource *res[2]; + void *ih_cookie[1]; + + struct ifnet *ifp; + uint32_t mvneta_if_flags; + uint32_t mvneta_media; + + int phy_attached; + enum mvneta_phy_mode phy_mode; + int phy_addr; + int phy_speed; /* PHY speed */ + boolean_t phy_fdx; /* Full duplex mode */ + boolean_t use_inband_status; /* In-band link status */ + + /* + * Link State control + */ + boolean_t linkup; + device_t miibus; + struct mii_data *mii; + uint8_t enaddr[ETHER_ADDR_LEN]; + struct ifmedia mvneta_ifmedia; + + bus_dma_tag_t rx_dtag; + bus_dma_tag_t rxbuf_dtag; + bus_dma_tag_t tx_dtag; + bus_dma_tag_t txmbuf_dtag; + struct mvneta_rx_ring rx_ring[MVNETA_RX_QNUM_MAX]; + struct mvneta_tx_ring tx_ring[MVNETA_TX_QNUM_MAX]; + + /* + * Maintance clock + */ + struct callout tick_ch; + + int cf_lpi; + int cf_fc; + int debug; + + /* + * Sysctl interfaces + */ + struct mvneta_sysctl_queue sysctl_rx_queue[MVNETA_RX_QNUM_MAX]; + struct mvneta_sysctl_queue sysctl_tx_queue[MVNETA_TX_QNUM_MAX]; + + /* + * MIB counter + */ + struct mvneta_sysctl_mib sysctl_mib[MVNETA_PORTMIB_NOCOUNTER]; + uint64_t counter_pdfc; + uint64_t counter_pofc; + uint32_t counter_watchdog; /* manual reset when clearing mib */ + uint32_t counter_watchdog_mib; /* reset after each mib update */ +}; +#define MVNETA_RX_RING(sc, q) \ + (&(sc)->rx_ring[(q)]) +#define MVNETA_TX_RING(sc, q) \ + (&(sc)->tx_ring[(q)]) + +int mvneta_attach(device_t); + +#ifdef FDT +int mvneta_fdt_mac_address(struct mvneta_softc *, uint8_t *); +#endif + +#endif /* _IF_MVNETAVAR_H_ */ |