From 22831f5cba7b6737d5d759ba4d96c649ff44645f Mon Sep 17 00:00:00 2001 From: christos Date: Sun, 1 Feb 2015 19:32:59 +0000 Subject: [PATCH] PR/49621: Robert Sprowson: Add detach function to if_cpsw --- sys/arch/arm/omap/if_cpsw.c | 62 +++++++++++++++++++++++++++++++++++-- 1 file changed, 59 insertions(+), 3 deletions(-) diff --git a/sys/arch/arm/omap/if_cpsw.c b/sys/arch/arm/omap/if_cpsw.c index cfba392891d4..d8f409a3e6bd 100644 --- a/sys/arch/arm/omap/if_cpsw.c +++ b/sys/arch/arm/omap/if_cpsw.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_cpsw.c,v 1.6 2014/04/09 20:52:14 hans Exp $ */ +/* $NetBSD: if_cpsw.c,v 1.7 2015/02/01 19:32:59 christos Exp $ */ /* * Copyright (c) 2013 Jonathan A. Kollasch @@ -53,7 +53,7 @@ */ #include -__KERNEL_RCSID(1, "$NetBSD: if_cpsw.c,v 1.6 2014/04/09 20:52:14 hans Exp $"); +__KERNEL_RCSID(1, "$NetBSD: if_cpsw.c,v 1.7 2015/02/01 19:32:59 christos Exp $"); #include #include @@ -115,6 +115,7 @@ struct cpsw_softc { device_t sc_dev; bus_space_tag_t sc_bst; bus_space_handle_t sc_bsh; + bus_size_t sc_bss; bus_dma_tag_t sc_bdt; bus_space_handle_t sc_bsh_txdescs; bus_space_handle_t sc_bsh_rxdescs; @@ -123,6 +124,7 @@ struct cpsw_softc { struct ethercom sc_ec; struct mii_data sc_mii; bool sc_phy_has_1000t; + bool sc_attached; callout_t sc_tick_ch; void *sc_ih; struct cpsw_ring_data *sc_rdp; @@ -145,6 +147,7 @@ struct cpsw_softc { static int cpsw_match(device_t, cfdata_t, void *); static void cpsw_attach(device_t, device_t, void *); +static int cpsw_detach(device_t, int); static void cpsw_start(struct ifnet *); static int cpsw_ioctl(struct ifnet *, u_long, void *); @@ -170,7 +173,7 @@ static int cpsw_miscintr(void *); static int cpsw_ale_update_addresses(struct cpsw_softc *, int purge); CFATTACH_DECL_NEW(cpsw, sizeof(struct cpsw_softc), - cpsw_match, cpsw_attach, NULL, NULL); + cpsw_match, cpsw_attach, cpsw_detach, NULL); #undef KERNHIST #include @@ -336,6 +339,55 @@ cpsw_phy_has_1000t(struct cpsw_softc * const sc) return false; } +static int +cpsw_detach(device_t self, int flags) +{ + struct cpsw_softc * const sc = device_private(self); + struct ifnet *ifp = &sc->sc_ec.ec_if; + u_int i; + + /* Succeed now if there's no work to do. */ + if (!sc->sc_attached) + return 0; + + sc->sc_attached = false; + + /* Stop the interface. Callouts are stopped in it. */ + cpsw_stop(ifp, 1); + + /* Destroy our callout. */ + callout_destroy(&sc->sc_tick_ch); + + /* Let go of the interrupts */ + intr_disestablish(sc->sc_rxthih); + intr_disestablish(sc->sc_rxih); + intr_disestablish(sc->sc_txih); + intr_disestablish(sc->sc_miscih); + + /* Delete all media. */ + ifmedia_delete_instance(&sc->sc_mii.mii_media, IFM_INST_ANY); + + ether_ifdetach(ifp); + if_detach(ifp); + + /* Free the packet padding buffer */ + kmem_free(sc->sc_txpad, ETHER_MIN_LEN); + bus_dmamap_destroy(sc->sc_bdt, sc->sc_txpad_dm); + + /* Destroy all the descriptors */ + for (i = 0; i < CPSW_NTXDESCS; i++) + bus_dmamap_destroy(sc->sc_bdt, sc->sc_rdp->tx_dm[i]); + for (i = 0; i < CPSW_NRXDESCS; i++) + bus_dmamap_destroy(sc->sc_bdt, sc->sc_rdp->rx_dm[i]); + kmem_free(sc->sc_rdp, sizeof(*sc->sc_rdp)); + + /* Unmap */ + bus_space_unmap(sc->sc_bst, sc->sc_bsh, sc->sc_bss); + + + return 0; +} + static void cpsw_attach(device_t parent, device_t self, void *aux) { @@ -398,6 +450,7 @@ cpsw_attach(device_t parent, device_t self, void *aux) IPL_VM, IST_LEVEL, cpsw_miscintr, sc); sc->sc_bst = oa->obio_iot; + sc->sc_bss = oa->obio_size; sc->sc_bdt = oa->obio_dmat; error = bus_space_map(sc->sc_bst, oa->obio_addr, oa->obio_size, 0, @@ -515,6 +568,9 @@ cpsw_attach(device_t parent, device_t self, void *aux) if_attach(ifp); ether_ifattach(ifp, sc->sc_enaddr); + /* The attach is successful. */ + sc->sc_attached = true; + return; }