summaryrefslogtreecommitdiffstats
path: root/sys/dev/hme
diff options
context:
space:
mode:
authortmm <tmm@FreeBSD.org>2003-01-09 00:45:10 +0000
committertmm <tmm@FreeBSD.org>2003-01-09 00:45:10 +0000
commitc1f62b116da233e3f8b8c4cf1b84df4f40ca2633 (patch)
tree1f434fbb34b47f7e7f77bfa126173dc1155de01f /sys/dev/hme
parent186300a2ca9c50556d656c3ae2dba83969a65d7f (diff)
downloadFreeBSD-src-c1f62b116da233e3f8b8c4cf1b84df4f40ca2633.zip
FreeBSD-src-c1f62b116da233e3f8b8c4cf1b84df4f40ca2633.tar.gz
Add detach, shutdown, suspend and resume methods.
Tested by: jake
Diffstat (limited to 'sys/dev/hme')
-rw-r--r--sys/dev/hme/if_hme.c55
-rw-r--r--sys/dev/hme/if_hme_pci.c43
-rw-r--r--sys/dev/hme/if_hme_sbus.c53
-rw-r--r--sys/dev/hme/if_hmevar.h3
4 files changed, 142 insertions, 12 deletions
diff --git a/sys/dev/hme/if_hme.c b/sys/dev/hme/if_hme.c
index 694fef3..779141b6 100644
--- a/sys/dev/hme/if_hme.c
+++ b/sys/dev/hme/if_hme.c
@@ -90,9 +90,6 @@ static void hme_stop(struct hme_softc *);
static int hme_ioctl(struct ifnet *, u_long, caddr_t);
static void hme_tick(void *);
static void hme_watchdog(struct ifnet *);
-#if 0
-static void hme_shutdown(void *);
-#endif
static void hme_init(void *);
static int hme_add_rxbuf(struct hme_softc *, unsigned int, int);
static int hme_meminit(struct hme_softc *);
@@ -345,6 +342,49 @@ fail_ptag:
return (error);
}
+void
+hme_detach(struct hme_softc *sc)
+{
+ struct ifnet *ifp = &sc->sc_arpcom.ac_if;
+ int i;
+
+ ether_ifdetach(ifp);
+ hme_stop(sc);
+ device_delete_child(sc->sc_dev, sc->sc_miibus);
+
+ for (i = 0; i < HME_NTXQ; i++) {
+ bus_dmamap_destroy(sc->sc_tdmatag,
+ sc->sc_rb.rb_txdesc[i].htx_dmamap);
+ }
+ bus_dmamap_destroy(sc->sc_rdmatag, sc->sc_rb.rb_spare_dmamap);
+ for (i = 0; i < HME_NRXDESC; i++) {
+ bus_dmamap_destroy(sc->sc_rdmatag,
+ sc->sc_rb.rb_rxdesc[i].hrx_dmamap);
+ }
+ bus_dmamap_unload(sc->sc_cdmatag, sc->sc_cdmamap);
+ bus_dmamem_free(sc->sc_cdmatag, sc->sc_rb.rb_membase, sc->sc_cdmamap);
+ bus_dma_tag_destroy(sc->sc_tdmatag);
+ bus_dma_tag_destroy(sc->sc_rdmatag);
+ bus_dma_tag_destroy(sc->sc_cdmatag);
+ bus_dma_tag_destroy(sc->sc_pdmatag);
+}
+
+void
+hme_suspend(struct hme_softc *sc)
+{
+
+ hme_stop(sc);
+}
+
+void
+hme_resume(struct hme_softc *sc)
+{
+ struct ifnet *ifp = &sc->sc_arpcom.ac_if;
+
+ if ((ifp->if_flags & IFF_UP) != 0)
+ hme_init(ifp);
+}
+
static void
hme_cdma_callback(void *xsc, bus_dma_segment_t *segs, int nsegs, int error)
{
@@ -1342,15 +1382,6 @@ hme_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
return (error);
}
-#if 0
-static void
-hme_shutdown(void *arg)
-{
-
- hme_stop((struct hme_softc *)arg);
-}
-#endif
-
/*
* Set up the logical address filter.
*/
diff --git a/sys/dev/hme/if_hme_pci.c b/sys/dev/hme/if_hme_pci.c
index 8e2409c..80ae966 100644
--- a/sys/dev/hme/if_hme_pci.c
+++ b/sys/dev/hme/if_hme_pci.c
@@ -77,11 +77,19 @@ struct hme_pci_softc {
static int hme_pci_probe(device_t);
static int hme_pci_attach(device_t);
+static int hme_pci_detach(device_t);
+static int hme_pci_suspend(device_t);
+static int hme_pci_resume(device_t);
static device_method_t hme_pci_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, hme_pci_probe),
DEVMETHOD(device_attach, hme_pci_attach),
+ DEVMETHOD(device_detach, hme_pci_detach),
+ DEVMETHOD(device_suspend, hme_pci_suspend),
+ DEVMETHOD(device_resume, hme_pci_resume),
+ /* Can just use the suspend method here. */
+ DEVMETHOD(device_shutdown, hme_pci_suspend),
/* bus interface */
DEVMETHOD(bus_print_child, bus_generic_print_child),
@@ -182,6 +190,7 @@ hme_pci_attach(device_t dev)
if ((error = bus_setup_intr(dev, hsc->hsc_ires, INTR_TYPE_NET, hme_intr,
sc, &hsc->hsc_ih)) != 0) {
device_printf(dev, "couldn't establish interrupt\n");
+ hme_detach(sc);
goto fail_ires;
}
return (0);
@@ -192,3 +201,37 @@ fail_sres:
bus_release_resource(dev, SYS_RES_MEMORY, hsc->hsc_srid, hsc->hsc_sres);
return (ENXIO);
}
+
+static int
+hme_pci_detach(device_t dev)
+{
+ struct hme_pci_softc *hsc = device_get_softc(dev);
+ struct hme_softc *sc = &hsc->hsc_hme;
+
+ hme_detach(sc);
+
+ bus_teardown_intr(dev, hsc->hsc_ires, hsc->hsc_ih);
+ bus_release_resource(dev, SYS_RES_IRQ, hsc->hsc_irid, hsc->hsc_ires);
+ bus_release_resource(dev, SYS_RES_MEMORY, hsc->hsc_srid, hsc->hsc_sres);
+ return (0);
+}
+
+static int
+hme_pci_suspend(device_t dev)
+{
+ struct hme_pci_softc *hsc = device_get_softc(dev);
+ struct hme_softc *sc = &hsc->hsc_hme;
+
+ hme_suspend(sc);
+ return (0);
+}
+
+static int
+hme_pci_resume(device_t dev)
+{
+ struct hme_pci_softc *hsc = device_get_softc(dev);
+ struct hme_softc *sc = &hsc->hsc_hme;
+
+ hme_resume(sc);
+ return (0);
+}
diff --git a/sys/dev/hme/if_hme_sbus.c b/sys/dev/hme/if_hme_sbus.c
index 46eaa45..66456fe 100644
--- a/sys/dev/hme/if_hme_sbus.c
+++ b/sys/dev/hme/if_hme_sbus.c
@@ -92,11 +92,19 @@ struct hme_sbus_softc {
static int hme_sbus_probe(device_t);
static int hme_sbus_attach(device_t);
+static int hme_sbus_detach(device_t);
+static int hme_sbus_suspend(device_t);
+static int hme_sbus_resume(device_t);
static device_method_t hme_sbus_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, hme_sbus_probe),
DEVMETHOD(device_attach, hme_sbus_attach),
+ DEVMETHOD(device_detach, hme_sbus_detach),
+ DEVMETHOD(device_suspend, hme_sbus_suspend),
+ DEVMETHOD(device_resume, hme_sbus_resume),
+ /* Can just use the suspend method here. */
+ DEVMETHOD(device_shutdown, hme_sbus_suspend),
/* bus interface */
DEVMETHOD(bus_print_child, bus_generic_print_child),
@@ -249,6 +257,7 @@ hme_sbus_attach(device_t dev)
if ((error = bus_setup_intr(dev, hsc->hsc_ires, INTR_TYPE_NET, hme_intr,
sc, &hsc->hsc_ih)) != 0) {
device_printf(dev, "couldn't establish interrupt\n");
+ hme_detach(sc);
goto fail_ires;
}
return (0);
@@ -274,3 +283,47 @@ fail_seb_res:
hsc->hsc_seb_res);
return (ENXIO);
}
+
+static int
+hme_sbus_detach(device_t dev)
+{
+ struct hme_sbus_softc *hsc = device_get_softc(dev);
+ struct hme_softc *sc = &hsc->hsc_hme;
+
+ hme_detach(sc);
+
+ bus_teardown_intr(dev, hsc->hsc_ires, hsc->hsc_ih);
+ if (hsc->hsc_mif_res != NULL) {
+ bus_release_resource(dev, SYS_RES_MEMORY, hsc->hsc_mif_rid,
+ hsc->hsc_mif_res);
+ }
+ bus_release_resource(dev, SYS_RES_MEMORY, hsc->hsc_mac_rid,
+ hsc->hsc_mac_res);
+ bus_release_resource(dev, SYS_RES_MEMORY, hsc->hsc_erx_rid,
+ hsc->hsc_erx_res);
+ bus_release_resource(dev, SYS_RES_MEMORY, hsc->hsc_etx_rid,
+ hsc->hsc_etx_res);
+ bus_release_resource(dev, SYS_RES_MEMORY, hsc->hsc_seb_rid,
+ hsc->hsc_seb_res);
+ return (0);
+}
+
+static int
+hme_sbus_suspend(device_t dev)
+{
+ struct hme_sbus_softc *hsc = device_get_softc(dev);
+ struct hme_softc *sc = &hsc->hsc_hme;
+
+ hme_suspend(sc);
+ return (0);
+}
+
+static int
+hme_sbus_resume(device_t dev)
+{
+ struct hme_sbus_softc *hsc = device_get_softc(dev);
+ struct hme_softc *sc = &hsc->hsc_hme;
+
+ hme_resume(sc);
+ return (0);
+}
diff --git a/sys/dev/hme/if_hmevar.h b/sys/dev/hme/if_hmevar.h
index 4c04cd3..7e1c5ed 100644
--- a/sys/dev/hme/if_hmevar.h
+++ b/sys/dev/hme/if_hmevar.h
@@ -150,6 +150,9 @@ struct hme_softc {
extern devclass_t hme_devclass;
int hme_config(struct hme_softc *);
+void hme_detach(struct hme_softc *);
+void hme_suspend(struct hme_softc *);
+void hme_resume(struct hme_softc *);
void hme_intr(void *);
/* MII methods & callbacks */
OpenPOWER on IntegriCloud