struct ath_bus_ops {
        void            (*read_cachesize)(struct ath_softc *sc, int *csz);
+       void            (*cleanup)(struct ath_softc *sc);
 };
 
 struct ath_softc {
        struct tasklet_struct bcon_tasklet;
        struct ath_hal *sc_ah;
        void __iomem *mem;
+       int irq;
        spinlock_t sc_resetlock;
        struct mutex mutex;
 
        sc->bus_ops->read_cachesize(sc, csz);
 }
 
+static inline void ath_bus_cleanup(struct ath_softc *sc)
+{
+       sc->bus_ops->cleanup(sc);
+}
+
 #endif /* CORE_H */
 
 };
 
 static void ath_detach(struct ath_softc *sc);
+static void ath_cleanup(struct ath_softc *sc);
 
 /* return bus cachesize in 4B word units */
 
                        rfkill_free(sc->rf_kill.rfkill);
 
                        /* Deinitialize the device */
-                       ath_detach(sc);
-                       if (to_pci_dev(sc->dev)->irq)
-                               free_irq(to_pci_dev(sc->dev)->irq, sc);
-                       pci_iounmap(to_pci_dev(sc->dev), sc->mem);
-                       pci_release_region(to_pci_dev(sc->dev), 0);
-                       pci_disable_device(to_pci_dev(sc->dev));
-                       ieee80211_free_hw(sc->hw);
+                       ath_cleanup(sc);
                        return -EIO;
                } else {
                        sc->sc_flags |= SC_OP_RFKILL_REGISTERED;
 }
 #endif /* CONFIG_RFKILL */
 
+static void ath_cleanup(struct ath_softc *sc)
+{
+       ath_detach(sc);
+       free_irq(sc->irq, sc);
+       ath_bus_cleanup(sc);
+       ieee80211_free_hw(sc->hw);
+}
+
 static void ath_detach(struct ath_softc *sc)
 {
        struct ieee80211_hw *hw = sc->hw;
        return "????";
 }
 
+static void ath_pci_cleanup(struct ath_softc *sc)
+{
+       struct pci_dev *pdev = to_pci_dev(sc->dev);
+
+       pci_iounmap(pdev, sc->mem);
+       pci_release_region(pdev, 0);
+       pci_disable_device(pdev);
+}
+
 static struct ath_bus_ops ath_pci_bus_ops = {
        .read_cachesize = ath_pci_read_cachesize,
+       .cleanup = ath_pci_cleanup,
 };
 
 static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                goto bad4;
        }
 
+       sc->irq = pdev->irq;
+
        ah = sc->sc_ah;
        printk(KERN_INFO
               "%s: Atheros AR%s MAC/BB Rev:%x "
        struct ieee80211_hw *hw = pci_get_drvdata(pdev);
        struct ath_softc *sc = hw->priv;
 
-       ath_detach(sc);
-       if (pdev->irq)
-               free_irq(pdev->irq, sc);
-       pci_iounmap(pdev, sc->mem);
-       pci_release_region(pdev, 0);
-       pci_disable_device(pdev);
-       ieee80211_free_hw(hw);
+       ath_cleanup(sc);
 }
 
 #ifdef CONFIG_PM