Module Name: src Committed By: christos Date: Sun Feb 1 19:32:59 UTC 2015
Modified Files: src/sys/arch/arm/omap: if_cpsw.c Log Message: PR/49621: Robert Sprowson: Add detach function to if_cpsw To generate a diff of this commit: cvs rdiff -u -r1.6 -r1.7 src/sys/arch/arm/omap/if_cpsw.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/arm/omap/if_cpsw.c diff -u src/sys/arch/arm/omap/if_cpsw.c:1.6 src/sys/arch/arm/omap/if_cpsw.c:1.7 --- src/sys/arch/arm/omap/if_cpsw.c:1.6 Wed Apr 9 16:52:14 2014 +++ src/sys/arch/arm/omap/if_cpsw.c Sun Feb 1 14:32:59 2015 @@ -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 <sys/cdefs.h> -__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 <sys/param.h> #include <sys/bus.h> @@ -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 <sys/kernhist.h> @@ -336,6 +339,55 @@ cpsw_phy_has_1000t(struct cpsw_softc * c 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 se 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 se if_attach(ifp); ether_ifattach(ifp, sc->sc_enaddr); + /* The attach is successful. */ + sc->sc_attached = true; + return; }