Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/neta/if_mvneta.c
Show First 20 Lines • Show All 216 Lines • ▼ Show 20 Lines | static device_method_t mvneta_methods[] = { | ||||
/* MDIO interface */ | /* MDIO interface */ | ||||
DEVMETHOD(mdio_readreg, mvneta_miibus_readreg), | DEVMETHOD(mdio_readreg, mvneta_miibus_readreg), | ||||
DEVMETHOD(mdio_writereg, mvneta_miibus_writereg), | DEVMETHOD(mdio_writereg, mvneta_miibus_writereg), | ||||
/* End */ | /* End */ | ||||
DEVMETHOD_END | DEVMETHOD_END | ||||
}; | }; | ||||
static struct ofw_compat_data compat_data[] = { | |||||
{ "marvell,armada-3700-neta", true }, | |||||
{ NULL, false } | |||||
}; | |||||
DEFINE_CLASS_0(mvneta, mvneta_driver, mvneta_methods, sizeof(struct mvneta_softc)); | DEFINE_CLASS_0(mvneta, mvneta_driver, mvneta_methods, sizeof(struct mvneta_softc)); | ||||
DRIVER_MODULE(miibus, mvneta, miibus_driver, miibus_devclass, 0, 0); | DRIVER_MODULE(miibus, mvneta, miibus_driver, miibus_devclass, 0, 0); | ||||
DRIVER_MODULE(mdio, mvneta, mdio_driver, mdio_devclass, 0, 0); | DRIVER_MODULE(mdio, mvneta, mdio_driver, mdio_devclass, 0, 0); | ||||
MODULE_DEPEND(mvneta, mdio, 1, 1, 1); | MODULE_DEPEND(mvneta, mdio, 1, 1, 1); | ||||
MODULE_DEPEND(mvneta, ether, 1, 1, 1); | MODULE_DEPEND(mvneta, ether, 1, 1, 1); | ||||
MODULE_DEPEND(mvneta, miibus, 1, 1, 1); | MODULE_DEPEND(mvneta, miibus, 1, 1, 1); | ||||
MODULE_DEPEND(mvneta, mvxpbm, 1, 1, 1); | SIMPLEBUS_PNP_INFO(compat_data); | ||||
/* | /* | ||||
* List of MIB register and names | * List of MIB register and names | ||||
*/ | */ | ||||
enum mvneta_mib_idx | enum mvneta_mib_idx | ||||
{ | { | ||||
MVNETA_MIB_RX_GOOD_OCT_IDX, | MVNETA_MIB_RX_GOOD_OCT_IDX, | ||||
MVNETA_MIB_RX_BAD_OCT_IDX, | MVNETA_MIB_RX_BAD_OCT_IDX, | ||||
▲ Show 20 Lines • Show All 363 Lines • ▼ Show 20 Lines | #if !defined(__aarch64__) | ||||
if ((MVNETA_READ(sc, MV_WIN_NETA_BASE(0)) & IO_WIN_COH_ATTR_MASK) == 0) { | if ((MVNETA_READ(sc, MV_WIN_NETA_BASE(0)) & IO_WIN_COH_ATTR_MASK) == 0) { | ||||
reg = MVNETA_READ(sc, MVNETA_PSNPCFG); | reg = MVNETA_READ(sc, MVNETA_PSNPCFG); | ||||
reg &= ~MVNETA_PSNPCFG_DESCSNP_MASK; | reg &= ~MVNETA_PSNPCFG_DESCSNP_MASK; | ||||
reg &= ~MVNETA_PSNPCFG_BUFSNP_MASK; | reg &= ~MVNETA_PSNPCFG_BUFSNP_MASK; | ||||
MVNETA_WRITE(sc, MVNETA_PSNPCFG, reg); | MVNETA_WRITE(sc, MVNETA_PSNPCFG, reg); | ||||
} | } | ||||
#endif | #endif | ||||
error = bus_setup_intr(self, sc->res[1], | |||||
INTR_TYPE_NET | INTR_MPSAFE, NULL, mvneta_intrs[0].handler, sc, | |||||
&sc->ih_cookie[0]); | |||||
if (error) { | |||||
device_printf(self, "could not setup %s\n", | |||||
mvneta_intrs[0].description); | |||||
mvneta_detach(self); | |||||
return (error); | |||||
} | |||||
/* | /* | ||||
* MAC address | * MAC address | ||||
*/ | */ | ||||
if (mvneta_get_mac_address(sc, sc->enaddr)) { | if (mvneta_get_mac_address(sc, sc->enaddr)) { | ||||
device_printf(self, "no mac address.\n"); | device_printf(self, "no mac address.\n"); | ||||
return (ENXIO); | return (ENXIO); | ||||
} | } | ||||
mvneta_set_mac_address(sc, sc->enaddr); | mvneta_set_mac_address(sc, sc->enaddr); | ||||
▲ Show 20 Lines • Show All 79 Lines • ▼ Show 20 Lines | #endif | ||||
for (q = 0; q < MVNETA_RX_QNUM_MAX; q++) { | for (q = 0; q < MVNETA_RX_QNUM_MAX; q++) { | ||||
error = mvneta_ring_init_rx_queue(sc, q); | error = mvneta_ring_init_rx_queue(sc, q); | ||||
if (error != 0) { | if (error != 0) { | ||||
mvneta_detach(self); | mvneta_detach(self); | ||||
return (error); | return (error); | ||||
} | } | ||||
} | } | ||||
ether_ifattach(ifp, sc->enaddr); | |||||
/* | /* | ||||
* Enable DMA engines and Initialize Device Registers. | * Enable DMA engines and Initialize Device Registers. | ||||
*/ | */ | ||||
MVNETA_WRITE(sc, MVNETA_PRXINIT, 0x00000000); | MVNETA_WRITE(sc, MVNETA_PRXINIT, 0x00000000); | ||||
MVNETA_WRITE(sc, MVNETA_PTXINIT, 0x00000000); | MVNETA_WRITE(sc, MVNETA_PTXINIT, 0x00000000); | ||||
MVNETA_WRITE(sc, MVNETA_PACC, MVNETA_PACC_ACCELERATIONMODE_EDM); | MVNETA_WRITE(sc, MVNETA_PACC, MVNETA_PACC_ACCELERATIONMODE_EDM); | ||||
mvneta_sc_lock(sc); | mvneta_sc_lock(sc); | ||||
mvneta_filter_setup(sc); | mvneta_filter_setup(sc); | ||||
▲ Show 20 Lines • Show All 113 Lines • ▼ Show 20 Lines | if (mvneta_has_switch(self)) { | ||||
bus_generic_attach(sc->dev); | bus_generic_attach(sc->dev); | ||||
bus_generic_attach(child); | bus_generic_attach(child); | ||||
} | } | ||||
/* Configure MAC media */ | /* Configure MAC media */ | ||||
mvneta_update_media(sc, ifm_target); | mvneta_update_media(sc, ifm_target); | ||||
} | } | ||||
sysctl_mvneta_init(sc); | ether_ifattach(ifp, sc->enaddr); | ||||
callout_reset(&sc->tick_ch, 0, mvneta_tick, sc); | callout_reset(&sc->tick_ch, 0, mvneta_tick, sc); | ||||
error = bus_setup_intr(self, sc->res[1], | sysctl_mvneta_init(sc); | ||||
INTR_TYPE_NET | INTR_MPSAFE, NULL, mvneta_intrs[0].handler, sc, | |||||
&sc->ih_cookie[0]); | |||||
if (error) { | |||||
device_printf(self, "could not setup %s\n", | |||||
mvneta_intrs[0].description); | |||||
ether_ifdetach(sc->ifp); | |||||
mvneta_detach(self); | |||||
return (error); | |||||
} | |||||
return (0); | return (0); | ||||
} | } | ||||
STATIC int | STATIC int | ||||
mvneta_detach(device_t dev) | mvneta_detach(device_t dev) | ||||
{ | { | ||||
struct mvneta_softc *sc; | struct mvneta_softc *sc; | ||||
struct ifnet *ifp; | |||||
int q; | int q; | ||||
sc = device_get_softc(dev); | sc = device_get_softc(dev); | ||||
ifp = sc->ifp; | |||||
if (device_is_attached(dev)) { | |||||
mvneta_stop(sc); | mvneta_stop(sc); | ||||
/* Detach network interface */ | callout_drain(&sc->tick_ch); | ||||
if (sc->ifp) | ether_ifdetach(sc->ifp); | ||||
if_free(sc->ifp); | } | ||||
for (q = 0; q < MVNETA_RX_QNUM_MAX; q++) | for (q = 0; q < MVNETA_RX_QNUM_MAX; q++) | ||||
mvneta_ring_dealloc_rx_queue(sc, q); | mvneta_ring_dealloc_rx_queue(sc, q); | ||||
for (q = 0; q < MVNETA_TX_QNUM_MAX; q++) | for (q = 0; q < MVNETA_TX_QNUM_MAX; q++) | ||||
mvneta_ring_dealloc_tx_queue(sc, q); | mvneta_ring_dealloc_tx_queue(sc, q); | ||||
device_delete_children(dev); | |||||
if (sc->ih_cookie[0] != NULL) | |||||
bus_teardown_intr(dev, sc->res[1], sc->ih_cookie[0]); | |||||
if (sc->tx_dtag != NULL) | if (sc->tx_dtag != NULL) | ||||
bus_dma_tag_destroy(sc->tx_dtag); | bus_dma_tag_destroy(sc->tx_dtag); | ||||
if (sc->rx_dtag != NULL) | if (sc->rx_dtag != NULL) | ||||
bus_dma_tag_destroy(sc->rx_dtag); | bus_dma_tag_destroy(sc->rx_dtag); | ||||
if (sc->txmbuf_dtag != NULL) | if (sc->txmbuf_dtag != NULL) | ||||
bus_dma_tag_destroy(sc->txmbuf_dtag); | bus_dma_tag_destroy(sc->txmbuf_dtag); | ||||
if (sc->rxbuf_dtag != NULL) | if (sc->rxbuf_dtag != NULL) | ||||
bus_dma_tag_destroy(sc->rxbuf_dtag); | bus_dma_tag_destroy(sc->rxbuf_dtag); | ||||
bus_release_resources(dev, res_spec, sc->res); | bus_release_resources(dev, res_spec, sc->res); | ||||
if (sc->ifp) | |||||
if_free(sc->ifp); | |||||
if (mtx_initialized(&sc->mtx)) | |||||
mtx_destroy(&sc->mtx); | |||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* MII | * MII | ||||
*/ | */ | ||||
STATIC int | STATIC int | ||||
mvneta_miibus_readreg(device_t dev, int phy, int reg) | mvneta_miibus_readreg(device_t dev, int phy, int reg) | ||||
▲ Show 20 Lines • Show All 357 Lines • ▼ Show 20 Lines | for (i = 0; i < MVNETA_RX_RING_CNT; i++) { | ||||
} | } | ||||
rxbuf = &rx->rxbuf[i]; | rxbuf = &rx->rxbuf[i]; | ||||
rxbuf->dmap = dmap; | rxbuf->dmap = dmap; | ||||
rxbuf->m = NULL; | rxbuf->m = NULL; | ||||
} | } | ||||
return (0); | return (0); | ||||
fail: | fail: | ||||
mvneta_rx_lockq(sc, q); | |||||
mvneta_ring_flush_rx_queue(sc, q); | |||||
mvneta_rx_unlockq(sc, q); | |||||
mvneta_ring_dealloc_rx_queue(sc, q); | mvneta_ring_dealloc_rx_queue(sc, q); | ||||
device_printf(sc->dev, "DMA Ring buffer allocation failure.\n"); | device_printf(sc->dev, "DMA Ring buffer allocation failure.\n"); | ||||
return (error); | return (error); | ||||
} | } | ||||
STATIC int | STATIC int | ||||
mvneta_ring_alloc_tx_queue(struct mvneta_softc *sc, int q) | mvneta_ring_alloc_tx_queue(struct mvneta_softc *sc, int q) | ||||
{ | { | ||||
Show All 25 Lines | device_printf(sc->dev, | ||||
"Could not setup buffer ring for TxQ(%d)\n", q); | "Could not setup buffer ring for TxQ(%d)\n", q); | ||||
error = ENOMEM; | error = ENOMEM; | ||||
goto fail; | goto fail; | ||||
} | } | ||||
#endif | #endif | ||||
return (0); | return (0); | ||||
fail: | fail: | ||||
mvneta_tx_lockq(sc, q); | |||||
mvneta_ring_flush_tx_queue(sc, q); | |||||
mvneta_tx_unlockq(sc, q); | |||||
mvneta_ring_dealloc_tx_queue(sc, q); | mvneta_ring_dealloc_tx_queue(sc, q); | ||||
device_printf(sc->dev, "DMA Ring buffer allocation failure.\n"); | device_printf(sc->dev, "DMA Ring buffer allocation failure.\n"); | ||||
return (error); | return (error); | ||||
} | } | ||||
STATIC void | STATIC void | ||||
mvneta_ring_dealloc_tx_queue(struct mvneta_softc *sc, int q) | mvneta_ring_dealloc_tx_queue(struct mvneta_softc *sc, int q) | ||||
{ | { | ||||
Show All 13 Lines | while (taskqueue_cancel(tx->taskq, &tx->task, NULL) != 0) | ||||
taskqueue_drain(tx->taskq, &tx->task); | taskqueue_drain(tx->taskq, &tx->task); | ||||
} | } | ||||
#ifdef MVNETA_MULTIQUEUE | #ifdef MVNETA_MULTIQUEUE | ||||
if (tx->br != NULL) | if (tx->br != NULL) | ||||
drbr_free(tx->br, M_DEVBUF); | drbr_free(tx->br, M_DEVBUF); | ||||
#endif | #endif | ||||
if (sc->txmbuf_dtag != NULL) { | if (sc->txmbuf_dtag != NULL) { | ||||
if (mtx_name(&tx->ring_mtx) != NULL) { | |||||
/* | |||||
* It is assumed that maps are being loaded after mutex | |||||
* is initialized. Therefore we can skip unloading maps | |||||
* when mutex is empty. | |||||
*/ | |||||
mvneta_tx_lockq(sc, q); | |||||
mvneta_ring_flush_tx_queue(sc, q); | |||||
mvneta_tx_unlockq(sc, q); | |||||
} | |||||
for (i = 0; i < MVNETA_TX_RING_CNT; i++) { | for (i = 0; i < MVNETA_TX_RING_CNT; i++) { | ||||
txbuf = &tx->txbuf[i]; | txbuf = &tx->txbuf[i]; | ||||
if (txbuf->dmap != NULL) { | if (txbuf->dmap != NULL) { | ||||
error = bus_dmamap_destroy(sc->txmbuf_dtag, | error = bus_dmamap_destroy(sc->txmbuf_dtag, | ||||
txbuf->dmap); | txbuf->dmap); | ||||
if (error != 0) { | if (error != 0) { | ||||
panic("%s: map busy for Tx descriptor (Q%d, %d)", | panic("%s: map busy for Tx descriptor (Q%d, %d)", | ||||
__func__, q, i); | __func__, q, i); | ||||
Show All 21 Lines | mvneta_ring_dealloc_rx_queue(struct mvneta_softc *sc, int q) | ||||
struct mvneta_rx_ring *rx; | struct mvneta_rx_ring *rx; | ||||
struct lro_ctrl *lro; | struct lro_ctrl *lro; | ||||
void *kva; | void *kva; | ||||
if (q >= MVNETA_RX_QNUM_MAX) | if (q >= MVNETA_RX_QNUM_MAX) | ||||
return; | return; | ||||
rx = MVNETA_RX_RING(sc, q); | rx = MVNETA_RX_RING(sc, q); | ||||
mvneta_ring_flush_rx_queue(sc, q); | |||||
if (rx->desc_pa != 0) | if (rx->desc_pa != 0) | ||||
bus_dmamap_unload(sc->rx_dtag, rx->desc_map); | bus_dmamap_unload(sc->rx_dtag, rx->desc_map); | ||||
kva = (void *)rx->desc; | kva = (void *)rx->desc; | ||||
if (kva != NULL) | if (kva != NULL) | ||||
bus_dmamem_free(sc->rx_dtag, rx->desc, rx->desc_map); | bus_dmamem_free(sc->rx_dtag, rx->desc, rx->desc_map); | ||||
▲ Show 20 Lines • Show All 2,261 Lines • Show Last 20 Lines |