static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid, const struct ath_bus_ops *bus_ops) { struct ath_hw *ah = NULL; struct ath_common *common; int ret = 0, i; int csz = 0; ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL); if (!ah) return -ENOMEM; ah->hw_version.devid = devid; ah->hw_version.subsysid = subsysid; sc->sc_ah = ah; common = ath9k_hw_common(ah); common->ops = &ath9k_common_ops; common->bus_ops = bus_ops; common->ah = ah; common->hw = sc->hw; common->priv = sc; common->debug_mask = ath9k_debug; spin_lock_init(&sc->wiphy_lock); spin_lock_init(&sc->sc_resetlock); spin_lock_init(&sc->sc_serial_rw); spin_lock_init(&sc->sc_pm_lock); mutex_init(&sc->mutex); tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc); tasklet_init(&sc->bcon_tasklet, ath_beacon_tasklet, (unsigned long)sc); /* * Cache line size is used to size and align various * structures used to communicate with the hardware. */ ath_read_cachesize(common, &csz); common->cachelsz = csz << 2; /* convert to bytes */ ret = ath9k_hw_init(ah); if (ret) { ath_print(common, ATH_DBG_FATAL, "Unable to initialize hardware; " "initialization status: %d\n", ret); goto err_hw; } ret = ath9k_init_debug(ah); if (ret) { ath_print(common, ATH_DBG_FATAL, "Unable to create debugfs files\n"); goto err_debug; } ret = ath9k_init_queues(sc); if (ret) goto err_queues; ret = ath9k_init_btcoex(sc); if (ret) goto err_btcoex; ath9k_init_crypto(sc); ath9k_init_channels_rates(sc); ath9k_init_misc(sc); return 0; err_btcoex: for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) if (ATH_TXQ_SETUP(sc, i)) ath_tx_cleanupq(sc, &sc->tx.txq[i]); err_queues: ath9k_exit_debug(ah); err_debug: ath9k_hw_deinit(ah); err_hw: tasklet_kill(&sc->intr_tq); tasklet_kill(&sc->bcon_tasklet); kfree(ah); sc->sc_ah = NULL; return ret; }
int ath9k_init_device(u16 devid, struct ath_softc *sc, const struct ath_bus_ops *bus_ops) { struct ieee80211_hw *hw = sc->hw; struct ath_common *common; struct ath_hw *ah; int error = 0; struct ath_regulatory *reg; /* Bring up device */ error = ath9k_init_softc(devid, sc, bus_ops); if (error != 0) goto error_init; ah = sc->sc_ah; common = ath9k_hw_common(ah); ath9k_set_hw_capab(sc, hw); /* Initialize regulatory */ error = ath_regd_init(&common->regulatory, sc->hw->wiphy, ath9k_reg_notifier); if (error) goto error_regd; reg = &common->regulatory; /* Setup TX DMA */ error = ath_tx_init(sc, ATH_TXBUF); if (error != 0) goto error_tx; /* Setup RX DMA */ error = ath_rx_init(sc, ATH_RXBUF); if (error != 0) goto error_rx; ath9k_init_txpower_limits(sc); #ifdef CONFIG_MAC80211_LEDS /* must be initialized before ieee80211_register_hw */ sc->led_cdev.default_trigger = ieee80211_create_tpt_led_trigger(sc->hw, IEEE80211_TPT_LEDTRIG_FL_RADIO, ath9k_tpt_blink, ARRAY_SIZE(ath9k_tpt_blink)); #endif INIT_WORK(&sc->hw_reset_work, ath_reset_work); INIT_WORK(&sc->hw_check_work, ath_hw_check); INIT_WORK(&sc->paprd_work, ath_paprd_calibrate); INIT_DELAYED_WORK(&sc->hw_pll_work, ath_hw_pll_work); /* Register with mac80211 */ error = ieee80211_register_hw(hw); if (error) goto error_register; error = ath9k_init_debug(ah); if (error) { ath_err(common, "Unable to create debugfs files\n"); goto error_world; } /* Handle world regulatory */ if (!ath_is_world_regd(reg)) { error = regulatory_hint(hw->wiphy, reg->alpha2); if (error) goto error_world; } setup_timer(&sc->rx_poll_timer, ath_rx_poll, (unsigned long)sc); sc->last_rssi = ATH_RSSI_DUMMY_MARKER; ath_init_leds(sc); ath_start_rfkill_poll(sc); return 0; error_world: ieee80211_unregister_hw(hw); error_register: ath_rx_cleanup(sc); error_rx: ath_tx_cleanup(sc); error_tx: /* Nothing */ error_regd: ath9k_deinit_softc(sc); error_init: return error; }
int ath9k_init_device(u16 devid, struct ath_softc *sc, const struct ath_bus_ops *bus_ops) { struct ieee80211_hw *hw = sc->hw; struct ath_common *common; struct ath_hw *ah; int error = 0; struct ath_regulatory *reg; /* Bring up device */ error = ath9k_init_softc(devid, sc, bus_ops); if (error) return error; ah = sc->sc_ah; common = ath9k_hw_common(ah); ath9k_set_hw_capab(sc, hw); /* Initialize regulatory */ error = ath_regd_init(&common->regulatory, sc->hw->wiphy, ath9k_reg_notifier); if (error) goto deinit; reg = &common->regulatory; /* Setup TX DMA */ error = ath_tx_init(sc, ATH_TXBUF); if (error != 0) goto deinit; /* Setup RX DMA */ error = ath_rx_init(sc, ATH_RXBUF); if (error != 0) goto deinit; ath9k_init_txpower_limits(sc); #ifdef CONFIG_MAC80211_LEDS /* must be initialized before ieee80211_register_hw */ sc->led_cdev.default_trigger = ieee80211_create_tpt_led_trigger(sc->hw, IEEE80211_TPT_LEDTRIG_FL_RADIO, ath9k_tpt_blink, ARRAY_SIZE(ath9k_tpt_blink)); #endif /* Register with mac80211 */ error = ieee80211_register_hw(hw); if (error) goto rx_cleanup; error = ath9k_init_debug(ah); if (error) { ath_err(common, "Unable to create debugfs files\n"); goto unregister; } /* Handle world regulatory */ if (!ath_is_world_regd(reg)) { error = regulatory_hint(hw->wiphy, reg->alpha2); if (error) goto debug_cleanup; } ath_init_leds(sc); ath_start_rfkill_poll(sc); return 0; debug_cleanup: ath9k_deinit_debug(sc); unregister: ieee80211_unregister_hw(hw); rx_cleanup: ath_rx_cleanup(sc); deinit: ath9k_deinit_softc(sc); return error; }