diff options
author | Pavel Roskin <proski@gnu.org> | 2010-01-30 21:37:24 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-02-01 15:40:09 -0500 |
commit | ab5132a26236e308c6d3d832a3e04fca351656d8 (patch) | |
tree | db473e3bd020a5e2f3fe02a381bb24e7b285ab5e /drivers | |
parent | e389900ed31975f3ce091764bf394b045058dad1 (diff) |
ath9k: fix access to freed data on unload
Calling ath_bus_cleanup() after ieee80211_free_hw() resulted in access
to common->bus_ops, which is already freed as part of the device data.
Remove the cleanup field in struct ath_bus_ops, as it was never used
properly. Remove ath_bus_cleanup(). Merge cleanup functions in place
of the ath_bus_cleanup() calls. Take care not to use any device data
after ieee80211_free_hw().
Signed-off-by: Pavel Roskin <proski@gnu.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/ath/ath.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ahb.c | 12 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ath9k.h | 5 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/pci.c | 18 |
4 files changed, 7 insertions, 29 deletions
diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h index 9e05648356fe..71fc960814f0 100644 --- a/drivers/net/wireless/ath/ath.h +++ b/drivers/net/wireless/ath/ath.h | |||
@@ -74,7 +74,6 @@ struct ath_common; | |||
74 | 74 | ||
75 | struct ath_bus_ops { | 75 | struct ath_bus_ops { |
76 | void (*read_cachesize)(struct ath_common *common, int *csz); | 76 | void (*read_cachesize)(struct ath_common *common, int *csz); |
77 | void (*cleanup)(struct ath_common *common); | ||
78 | bool (*eeprom_read)(struct ath_common *common, u32 off, u16 *data); | 77 | bool (*eeprom_read)(struct ath_common *common, u32 off, u16 *data); |
79 | void (*bt_coex_prep)(struct ath_common *common); | 78 | void (*bt_coex_prep)(struct ath_common *common); |
80 | }; | 79 | }; |
diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c index 9e62a569e816..ca4994f13151 100644 --- a/drivers/net/wireless/ath/ath9k/ahb.c +++ b/drivers/net/wireless/ath/ath9k/ahb.c | |||
@@ -27,12 +27,6 @@ static void ath_ahb_read_cachesize(struct ath_common *common, int *csz) | |||
27 | *csz = L1_CACHE_BYTES >> 2; | 27 | *csz = L1_CACHE_BYTES >> 2; |
28 | } | 28 | } |
29 | 29 | ||
30 | static void ath_ahb_cleanup(struct ath_common *common) | ||
31 | { | ||
32 | struct ath_softc *sc = (struct ath_softc *)common->priv; | ||
33 | iounmap(sc->mem); | ||
34 | } | ||
35 | |||
36 | static bool ath_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data) | 30 | static bool ath_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data) |
37 | { | 31 | { |
38 | struct ath_softc *sc = (struct ath_softc *)common->priv; | 32 | struct ath_softc *sc = (struct ath_softc *)common->priv; |
@@ -54,8 +48,6 @@ static bool ath_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data) | |||
54 | 48 | ||
55 | static struct ath_bus_ops ath_ahb_bus_ops = { | 49 | static struct ath_bus_ops ath_ahb_bus_ops = { |
56 | .read_cachesize = ath_ahb_read_cachesize, | 50 | .read_cachesize = ath_ahb_read_cachesize, |
57 | .cleanup = ath_ahb_cleanup, | ||
58 | |||
59 | .eeprom_read = ath_ahb_eeprom_read, | 51 | .eeprom_read = ath_ahb_eeprom_read, |
60 | }; | 52 | }; |
61 | 53 | ||
@@ -164,12 +156,12 @@ static int ath_ahb_remove(struct platform_device *pdev) | |||
164 | if (hw) { | 156 | if (hw) { |
165 | struct ath_wiphy *aphy = hw->priv; | 157 | struct ath_wiphy *aphy = hw->priv; |
166 | struct ath_softc *sc = aphy->sc; | 158 | struct ath_softc *sc = aphy->sc; |
167 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 159 | void __iomem *mem = sc->mem; |
168 | 160 | ||
169 | ath9k_deinit_device(sc); | 161 | ath9k_deinit_device(sc); |
170 | free_irq(sc->irq, sc); | 162 | free_irq(sc->irq, sc); |
171 | ieee80211_free_hw(sc->hw); | 163 | ieee80211_free_hw(sc->hw); |
172 | ath_bus_cleanup(common); | 164 | iounmap(mem); |
173 | platform_set_drvdata(pdev, NULL); | 165 | platform_set_drvdata(pdev, NULL); |
174 | } | 166 | } |
175 | 167 | ||
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 3f8a7e773d55..0ea340fd071c 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -538,11 +538,6 @@ static inline void ath_read_cachesize(struct ath_common *common, int *csz) | |||
538 | common->bus_ops->read_cachesize(common, csz); | 538 | common->bus_ops->read_cachesize(common, csz); |
539 | } | 539 | } |
540 | 540 | ||
541 | static inline void ath_bus_cleanup(struct ath_common *common) | ||
542 | { | ||
543 | common->bus_ops->cleanup(common); | ||
544 | } | ||
545 | |||
546 | extern struct ieee80211_ops ath9k_ops; | 541 | extern struct ieee80211_ops ath9k_ops; |
547 | extern int modparam_nohwcrypt; | 542 | extern int modparam_nohwcrypt; |
548 | 543 | ||
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index 4ae7b5f12029..f2afcbefc076 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c | |||
@@ -49,16 +49,6 @@ static void ath_pci_read_cachesize(struct ath_common *common, int *csz) | |||
49 | *csz = DEFAULT_CACHELINE >> 2; /* Use the default size */ | 49 | *csz = DEFAULT_CACHELINE >> 2; /* Use the default size */ |
50 | } | 50 | } |
51 | 51 | ||
52 | static void ath_pci_cleanup(struct ath_common *common) | ||
53 | { | ||
54 | struct ath_softc *sc = (struct ath_softc *) common->priv; | ||
55 | struct pci_dev *pdev = to_pci_dev(sc->dev); | ||
56 | |||
57 | pci_iounmap(pdev, sc->mem); | ||
58 | pci_disable_device(pdev); | ||
59 | pci_release_region(pdev, 0); | ||
60 | } | ||
61 | |||
62 | static bool ath_pci_eeprom_read(struct ath_common *common, u32 off, u16 *data) | 52 | static bool ath_pci_eeprom_read(struct ath_common *common, u32 off, u16 *data) |
63 | { | 53 | { |
64 | struct ath_hw *ah = (struct ath_hw *) common->ah; | 54 | struct ath_hw *ah = (struct ath_hw *) common->ah; |
@@ -98,7 +88,6 @@ static void ath_pci_bt_coex_prep(struct ath_common *common) | |||
98 | 88 | ||
99 | static const struct ath_bus_ops ath_pci_bus_ops = { | 89 | static const struct ath_bus_ops ath_pci_bus_ops = { |
100 | .read_cachesize = ath_pci_read_cachesize, | 90 | .read_cachesize = ath_pci_read_cachesize, |
101 | .cleanup = ath_pci_cleanup, | ||
102 | .eeprom_read = ath_pci_eeprom_read, | 91 | .eeprom_read = ath_pci_eeprom_read, |
103 | .bt_coex_prep = ath_pci_bt_coex_prep, | 92 | .bt_coex_prep = ath_pci_bt_coex_prep, |
104 | }; | 93 | }; |
@@ -245,12 +234,15 @@ static void ath_pci_remove(struct pci_dev *pdev) | |||
245 | struct ieee80211_hw *hw = pci_get_drvdata(pdev); | 234 | struct ieee80211_hw *hw = pci_get_drvdata(pdev); |
246 | struct ath_wiphy *aphy = hw->priv; | 235 | struct ath_wiphy *aphy = hw->priv; |
247 | struct ath_softc *sc = aphy->sc; | 236 | struct ath_softc *sc = aphy->sc; |
248 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 237 | void __iomem *mem = sc->mem; |
249 | 238 | ||
250 | ath9k_deinit_device(sc); | 239 | ath9k_deinit_device(sc); |
251 | free_irq(sc->irq, sc); | 240 | free_irq(sc->irq, sc); |
252 | ieee80211_free_hw(sc->hw); | 241 | ieee80211_free_hw(sc->hw); |
253 | ath_bus_cleanup(common); | 242 | |
243 | pci_iounmap(pdev, mem); | ||
244 | pci_disable_device(pdev); | ||
245 | pci_release_region(pdev, 0); | ||
254 | } | 246 | } |
255 | 247 | ||
256 | #ifdef CONFIG_PM | 248 | #ifdef CONFIG_PM |