ath5k: allocate ath5k_hw prior to initializing hw

We can propagate better errors upon failed hw initialization,
and set up the ath_common structure for attach purposes. This
will become important once we start using the ath_common
for read/write ops.

Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
Luis R. Rodriguez 2009-09-10 18:04:47 -07:00 committed by John W. Linville
parent 9e4bffd233
commit 9adca126db
4 changed files with 22 additions and 25 deletions

View file

@ -51,7 +51,7 @@ struct ath_common {
u8 curbssid[ETH_ALEN]; u8 curbssid[ETH_ALEN];
u8 bssidmask[ETH_ALEN]; u8 bssidmask[ETH_ALEN];
struct ath_regulatory regulatory; struct ath_regulatory regulatory;
struct ath_ops *ops; const struct ath_ops *ops;
}; };
struct sk_buff *ath_rxbuf_alloc(struct ath_common *common, struct sk_buff *ath_rxbuf_alloc(struct ath_common *common,

View file

@ -1147,7 +1147,7 @@ struct ath5k_hw {
*/ */
/* Attach/Detach Functions */ /* Attach/Detach Functions */
extern struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc); extern int ath5k_hw_attach(struct ath5k_softc *sc);
extern void ath5k_hw_detach(struct ath5k_hw *ah); extern void ath5k_hw_detach(struct ath5k_hw *ah);
/* LED functions */ /* LED functions */

View file

@ -101,28 +101,15 @@ static int ath5k_hw_post(struct ath5k_hw *ah)
* -ENODEV if the device is not supported or prints an error msg if something * -ENODEV if the device is not supported or prints an error msg if something
* else went wrong. * else went wrong.
*/ */
struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc) int ath5k_hw_attach(struct ath5k_softc *sc)
{ {
struct ath5k_hw *ah; struct ath5k_hw *ah = sc->ah;
struct ath_common *common; struct ath_common *common;
struct pci_dev *pdev = sc->pdev; struct pci_dev *pdev = sc->pdev;
struct ath5k_eeprom_info *ee; struct ath5k_eeprom_info *ee;
int ret; int ret;
u32 srev; u32 srev;
/*If we passed the test malloc a ath5k_hw struct*/
ah = kzalloc(sizeof(struct ath5k_hw), GFP_KERNEL);
if (ah == NULL) {
ret = -ENOMEM;
ATH5K_ERR(sc, "out of memory\n");
goto err;
}
ah->ah_sc = sc;
ah->ah_sc->ah = ah;
ah->ah_iobase = sc->iobase;
common = ath5k_hw_common(ah);
/* /*
* HW information * HW information
*/ */
@ -347,11 +334,10 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc)
/* turn on HW LEDs */ /* turn on HW LEDs */
ath5k_hw_set_ledstate(ah, AR5K_LED_INIT); ath5k_hw_set_ledstate(ah, AR5K_LED_INIT);
return ah; return 0;
err_free: err_free:
kfree(ah); kfree(ah);
err: return ret;
return ERR_PTR(ret);
} }
/** /**
@ -371,5 +357,4 @@ void ath5k_hw_detach(struct ath5k_hw *ah)
ath5k_eeprom_detach(ah); ath5k_eeprom_detach(ah);
/* assume interrupts are down */ /* assume interrupts are down */
kfree(ah);
} }

View file

@ -565,16 +565,25 @@ ath5k_pci_probe(struct pci_dev *pdev,
goto err_free; goto err_free;
} }
/* Initialize device */ /*If we passed the test malloc a ath5k_hw struct*/
sc->ah = ath5k_hw_attach(sc); sc->ah = kzalloc(sizeof(struct ath5k_hw), GFP_KERNEL);
if (IS_ERR(sc->ah)) { if (!sc->ah) {
ret = PTR_ERR(sc->ah); ret = -ENOMEM;
ATH5K_ERR(sc, "out of memory\n");
goto err_irq; goto err_irq;
} }
sc->ah->ah_sc = sc;
sc->ah->ah_iobase = sc->iobase;
common = ath5k_hw_common(sc->ah); common = ath5k_hw_common(sc->ah);
common->cachelsz = csz << 2; /* convert to bytes */ common->cachelsz = csz << 2; /* convert to bytes */
/* Initialize device */
ret = ath5k_hw_attach(sc);
if (ret) {
goto err_free_ah;
}
/* set up multi-rate retry capabilities */ /* set up multi-rate retry capabilities */
if (sc->ah->ah_version == AR5K_AR5212) { if (sc->ah->ah_version == AR5K_AR5212) {
hw->max_rates = 4; hw->max_rates = 4;
@ -643,6 +652,8 @@ err_ah:
ath5k_hw_detach(sc->ah); ath5k_hw_detach(sc->ah);
err_irq: err_irq:
free_irq(pdev->irq, sc); free_irq(pdev->irq, sc);
err_free_ah:
kfree(sc->ah);
err_free: err_free:
ieee80211_free_hw(hw); ieee80211_free_hw(hw);
err_map: err_map:
@ -664,6 +675,7 @@ ath5k_pci_remove(struct pci_dev *pdev)
ath5k_debug_finish_device(sc); ath5k_debug_finish_device(sc);
ath5k_detach(pdev, hw); ath5k_detach(pdev, hw);
ath5k_hw_detach(sc->ah); ath5k_hw_detach(sc->ah);
kfree(sc->ah);
free_irq(pdev->irq, sc); free_irq(pdev->irq, sc);
pci_iounmap(pdev, sc->iobase); pci_iounmap(pdev, sc->iobase);
pci_release_region(pdev, 0); pci_release_region(pdev, 0);