summaryrefslogtreecommitdiff
path: root/sys/dev/pci/if_iwn.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/pci/if_iwn.c')
-rw-r--r--sys/dev/pci/if_iwn.c45
1 files changed, 43 insertions, 2 deletions
diff --git a/sys/dev/pci/if_iwn.c b/sys/dev/pci/if_iwn.c
index bb5acd0bb30..ade4a6ae78c 100644
--- a/sys/dev/pci/if_iwn.c
+++ b/sys/dev/pci/if_iwn.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_iwn.c,v 1.62 2009/08/10 17:21:15 damien Exp $ */
+/* $OpenBSD: if_iwn.c,v 1.63 2009/09/20 20:04:07 damien Exp $ */
/*-
* Copyright (c) 2007-2009 Damien Bergamini <damien.bergamini@free.fr>
@@ -99,6 +99,7 @@ void iwn_sensor_attach(struct iwn_softc *);
#if NBPFILTER > 0
void iwn_radiotap_attach(struct iwn_softc *);
#endif
+int iwn_detach(struct device *, int);
void iwn_power(int, void *);
int iwn_nic_lock(struct iwn_softc *);
int iwn_eeprom_lock(struct iwn_softc *);
@@ -318,7 +319,7 @@ struct cfdriver iwn_cd = {
};
struct cfattach iwn_ca = {
- sizeof (struct iwn_softc), iwn_match, iwn_attach
+ sizeof (struct iwn_softc), iwn_match, iwn_attach, iwn_detach
};
int
@@ -646,6 +647,46 @@ iwn_radiotap_attach(struct iwn_softc *sc)
}
#endif
+int
+iwn_detach(struct device *self, int flags)
+{
+ struct iwn_softc *sc = (struct iwn_softc *)self;
+ struct ifnet *ifp = &sc->sc_ic.ic_if;
+ int s, qid;
+
+ s = splnet();
+ timeout_del(&sc->calib_to);
+
+ /* Uninstall interrupt handler. */
+ if (sc->sc_ih != NULL)
+ pci_intr_disestablish(sc->sc_pct, sc->sc_ih);
+
+ ieee80211_ifdetach(ifp);
+ if_detach(ifp);
+ splx(s);
+
+ /* Free DMA resources. */
+ iwn_free_rx_ring(sc, &sc->rxq);
+ for (qid = 0; qid < sc->sc_hal->ntxqs; qid++)
+ iwn_free_tx_ring(sc, &sc->txq[qid]);
+ iwn_free_sched(sc);
+ iwn_free_kw(sc);
+ iwn_free_fwmem(sc);
+
+#ifndef SMALL_KERNEL
+ /* Detach the thermal sensor. */
+ sensor_detach(&sc->sensordev, &sc->sensor);
+ sensordev_deinstall(&sc->sensordev);
+#endif
+
+ if (sc->powerhook != NULL)
+ powerhook_disestablish(sc->powerhook);
+
+ bus_space_unmap(sc->sc_st, sc->sc_sh, sc->sc_sz);
+
+ return 0;
+}
+
void
iwn_power(int why, void *arg)
{