/* * Drain the transmit queues and reclaim resources. */ static void ath_drain_txq(struct ath_softc *sc) { #ifdef ATH_SUPPORT_HTC u_int16_t i; struct ath_hal *ah = sc->sc_ah; /* drain all host endpoints */ for (i = 0; i < NUM_TX_EP; i++) if (ATH_TXQ_SETUP(sc, i)) ath_tx_drainep(sc, &sc->sc_txep[i]); HTCDrainAllEp(sc->sc_host_htc_handle); /* stop target wireless DMA */ if (!sc->sc_invalid) { for (i = 0; i < NUM_TX_EP; i++) if (ATH_TXQ_SETUP(sc, i)) { u_int32_t hwq_num; hwq_num = adf_os_htonl(sc->sc_txep[i].hwq_num); ath_hal_tx99_tx_stopdma(ah, hwq_num); } } ath_hal_tx99_drain_alltxq(ah); #else /* stop beacon queue. stop and abort all tx qs, flush ath buffer queue */ ath_draintxq(sc, AH_FALSE, 0); /* stop xmit side */ #endif }
static void ath9k_deinit_softc(struct ath_softc *sc) { int i = 0; if (sc->sbands[IEEE80211_BAND_2GHZ].channels) kfree(sc->sbands[IEEE80211_BAND_2GHZ].channels); if (sc->sbands[IEEE80211_BAND_5GHZ].channels) kfree(sc->sbands[IEEE80211_BAND_5GHZ].channels); if ((sc->btcoex.no_stomp_timer) && sc->sc_ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) ath_gen_timer_free(sc->sc_ah, sc->btcoex.no_stomp_timer); for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) if (ATH_TXQ_SETUP(sc, i)) ath_tx_cleanupq(sc, &sc->tx.txq[i]); ath9k_exit_debug(sc->sc_ah); ath9k_hw_deinit(sc->sc_ah); tasklet_kill(&sc->intr_tq); tasklet_kill(&sc->bcon_tasklet); kfree(sc->sc_ah); sc->sc_ah = NULL; }
static void ath9k_deinit_softc(struct ath_softc *sc) { int i = 0; if (sc->sbands[IEEE80211_BAND_2GHZ].channels) kfree(sc->sbands[IEEE80211_BAND_2GHZ].channels); if (sc->sbands[IEEE80211_BAND_5GHZ].channels) kfree(sc->sbands[IEEE80211_BAND_5GHZ].channels); if ((sc->btcoex.no_stomp_timer) && ath9k_hw_get_btcoex_scheme(sc->sc_ah) == ATH_BTCOEX_CFG_3WIRE) ath_gen_timer_free(sc->sc_ah, sc->btcoex.no_stomp_timer); if (ath9k_hw_get_btcoex_scheme(sc->sc_ah) == ATH_BTCOEX_CFG_MCI) ath_mci_cleanup(sc); for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) if (ATH_TXQ_SETUP(sc, i)) ath_tx_cleanupq(sc, &sc->tx.txq[i]); ath9k_hw_deinit(sc->sc_ah); kfree(sc->sc_ah); sc->sc_ah = NULL; }
void ath_ald_update_frame_stats(struct ath_softc *sc, struct ath_buf *bf, struct ath_tx_status *ts) { struct ieee80211_frame *wh; int type; int bfUsed = 0; u_int32_t ptime = 0; u_int32_t airtime = 0; int i; void *ds = bf->bf_lastbf->bf_desc; wh = (struct ieee80211_frame *)wbuf_header(bf->bf_mpdu); type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; if((type == IEEE80211_FC0_TYPE_DATA) && (!IEEE80211_IS_MULTICAST(wh->i_addr1)) && (!IEEE80211_IS_BROADCAST(wh->i_addr1))){ for(i=0; i < HAL_NUM_TX_QUEUES; i++) { if (ATH_TXQ_SETUP(sc, i)) { bfUsed += sc->sc_txq[i].axq_num_buf_used; } } ptime = sc->sc_ald.sc_ald_txairtime; airtime = ath_hal_txcalcairtime(sc->sc_ah, ds, ts, AH_FALSE, 1, 1); sc->sc_ald.sc_ald_txairtime += airtime; if (ptime > sc->sc_ald.sc_ald_txairtime) { sc->sc_ald.sc_ald_txairtime = airtime; sc->sc_ald.sc_ald_pktnum = 0; } if (airtime) { sc->sc_ald.sc_ald_pktlen += (bf->bf_isaggr ? bf->bf_al : bf->bf_frmlen); sc->sc_ald.sc_ald_pktnum += bf->bf_nframes; sc->sc_ald.sc_ald_bfused += bfUsed; sc->sc_ald.sc_ald_counter += 1; } } }
static int ath9k_init_queues(struct ath_softc *sc) { struct ath_common *common = ath9k_hw_common(sc->sc_ah); int i = 0; for (i = 0; i < ARRAY_SIZE(sc->tx.hwq_map); i++) sc->tx.hwq_map[i] = -1; sc->beacon.beaconq = ath9k_hw_beaconq_setup(sc->sc_ah); if (sc->beacon.beaconq == -1) { ath_print(common, ATH_DBG_FATAL, "Unable to setup a beacon xmit queue\n"); goto err; } sc->beacon.cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0); if (sc->beacon.cabq == NULL) { ath_print(common, ATH_DBG_FATAL, "Unable to setup CAB xmit queue\n"); goto err; } sc->config.cabqReadytime = ATH_CABQ_READY_TIME; ath_cabq_update(sc); if (!ath_tx_setup(sc, ATH9K_WME_AC_BK)) { ath_print(common, ATH_DBG_FATAL, "Unable to setup xmit queue for BK traffic\n"); goto err; } if (!ath_tx_setup(sc, ATH9K_WME_AC_BE)) { ath_print(common, ATH_DBG_FATAL, "Unable to setup xmit queue for BE traffic\n"); goto err; } if (!ath_tx_setup(sc, ATH9K_WME_AC_VI)) { ath_print(common, ATH_DBG_FATAL, "Unable to setup xmit queue for VI traffic\n"); goto err; } if (!ath_tx_setup(sc, ATH9K_WME_AC_VO)) { ath_print(common, ATH_DBG_FATAL, "Unable to setup xmit queue for VO traffic\n"); goto err; } return 0; err: for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) if (ATH_TXQ_SETUP(sc, i)) ath_tx_cleanupq(sc, &sc->tx.txq[i]); return -EIO; }
/* * Drain the transmit queues and reclaim resources. */ static void ath_drain_txq(struct ath_softc *sc) { #ifdef ATH_SUPPORT_HTC u_int16_t i; struct ath_hal *ah = sc->sc_ah; /* drain all host endpoints */ for (i = 0; i < NUM_TX_EP; i++) if (ATH_TXQ_SETUP(sc, i)) ath_tx_drainep(sc, &sc->sc_txep[i]); HTCDrainAllEp(sc->sc_host_htc_handle); /* stop target wireless DMA */ if (!sc->sc_invalid) { for (i = 0; i < NUM_TX_EP; i++) if (ATH_TXQ_SETUP(sc, i)) { u_int32_t hwq_num; hwq_num = adf_os_htonl(sc->sc_txep[i].hwq_num); ath_hal_tx99_tx_stopdma(ah, hwq_num); } } ath_hal_tx99_drain_alltxq(ah); #else /* stop beacon queue. The beacon will be freed when we go to INIT state */ if (!sc->sc_invalid) { if ( !(sc->sc_fastabortenabled && (sc->sc_reset_type == ATH_RESET_NOLOSS)) ){ (void) ath_hal_stoptxdma(sc->sc_ah, sc->sc_bhalq, 0); } if (sc->sc_fastabortenabled) { /* fast tx abort */ ath_hal_aborttxdma(sc->sc_ah); } } /* to drain tx dataq */ sc->sc_ath_ops.tx_flush(sc); #endif }
static void ath9k_deinit_softc(struct ath_softc *sc) { int i = 0; ath9k_deinit_btcoex(sc); for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) if (ATH_TXQ_SETUP(sc, i)) ath_tx_cleanupq(sc, &sc->tx.txq[i]); ath9k_hw_deinit(sc->sc_ah); if (sc->dfs_detector != NULL) sc->dfs_detector->exit(sc->dfs_detector); ath9k_eeprom_release(sc); }
static void ath9k_deinit_softc(struct ath_softc *sc) { int i = 0; if (sc->sbands[IEEE80211_BAND_2GHZ].channels) kfree(sc->sbands[IEEE80211_BAND_2GHZ].channels); if (sc->sbands[IEEE80211_BAND_5GHZ].channels) kfree(sc->sbands[IEEE80211_BAND_5GHZ].channels); ath9k_deinit_btcoex(sc); for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) if (ATH_TXQ_SETUP(sc, i)) ath_tx_cleanupq(sc, &sc->tx.txq[i]); ath9k_hw_deinit(sc->sc_ah); kfree(sc->sc_ah); sc->sc_ah = NULL; }
/* * TX polling - checks if the TX engine is stuck somewhere * and issues a chip reset if so. */ void ath_tx_complete_poll_work(struct work_struct *work) { struct ath_softc *sc = container_of(work, struct ath_softc, tx_complete_work.work); struct ath_txq *txq; int i; bool needreset = false; #ifdef CONFIG_ATH9K_DEBUGFS sc->tx_complete_poll_work_seen++; #endif for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) if (ATH_TXQ_SETUP(sc, i)) { txq = &sc->tx.txq[i]; ath_txq_lock(sc, txq); if (txq->axq_depth) { if (txq->axq_tx_inprogress) { needreset = true; ath_txq_unlock(sc, txq); break; } else { txq->axq_tx_inprogress = true; } } ath_txq_unlock_complete(sc, txq); } if (needreset) { ath_dbg(ath9k_hw_common(sc->sc_ah), RESET, "tx hung, resetting the chip\n"); RESET_STAT_INC(sc, RESET_TYPE_TX_HANG); ieee80211_queue_work(sc->hw, &sc->hw_reset_work); return; } ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, msecs_to_jiffies(ATH_TX_COMPLETE_POLL_INT)); }
static int ath9k_init_softc(u16 devid, struct ath_softc *sc, const struct ath_bus_ops *bus_ops) { struct ath9k_platform_data *pdata = sc->dev->platform_data; 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 = sc->hw; ah->hw_version.devid = devid; ah->reg_ops.read = ath9k_ioread32; ah->reg_ops.write = ath9k_iowrite32; ah->reg_ops.rmw = ath9k_reg_rmw; atomic_set(&ah->intr_ref_cnt, -1); sc->sc_ah = ah; sc->dfs_detector = dfs_pattern_detector_init(NL80211_DFS_UNSET); if (!pdata) { ah->ah_flags |= AH_USE_EEPROM; sc->sc_ah->led_pin = -1; } else { sc->sc_ah->gpio_mask = pdata->gpio_mask; sc->sc_ah->gpio_val = pdata->gpio_val; sc->sc_ah->led_pin = pdata->led_pin; ah->is_clk_25mhz = pdata->is_clk_25mhz; ah->get_mac_revision = pdata->get_mac_revision; ah->external_reset = pdata->external_reset; } common = ath9k_hw_common(ah); common->ops = &ah->reg_ops; common->bus_ops = bus_ops; common->ah = ah; common->hw = sc->hw; common->priv = sc; common->debug_mask = ath9k_debug; common->btcoex_enabled = ath9k_btcoex_enable == 1; common->disable_ani = false; spin_lock_init(&common->cc_lock); spin_lock_init(&sc->sc_serial_rw); spin_lock_init(&sc->sc_pm_lock); mutex_init(&sc->mutex); #ifdef CONFIG_ATH9K_DEBUGFS spin_lock_init(&sc->nodes_lock); INIT_LIST_HEAD(&sc->nodes); #endif #ifdef CONFIG_ATH9K_MAC_DEBUG spin_lock_init(&sc->debug.samp_lock); #endif 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 */ /* Initializes the hardware for all supported chipsets */ ret = ath9k_hw_init(ah); if (ret) goto err_hw; if (pdata && pdata->macaddr) memcpy(common->macaddr, pdata->macaddr, ETH_ALEN); ret = ath9k_init_queues(sc); if (ret) goto err_queues; ret = ath9k_init_btcoex(sc); if (ret) goto err_btcoex; ret = ath9k_init_channels_rates(sc); if (ret) goto err_btcoex; ath9k_cmn_init_crypto(sc->sc_ah); 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_hw_deinit(ah); err_hw: kfree(ah); sc->sc_ah = NULL; return ret; }
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; }
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 = sc->hw; ah->hw_version.devid = devid; ah->hw_version.subsysid = subsysid; sc->sc_ah = ah; if (!sc->dev->platform_data) ah->ah_flags |= AH_USE_EEPROM; 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; common->btcoex_enabled = ath9k_btcoex_enable == 1; spin_lock_init(&common->cc_lock); spin_lock_init(&sc->sc_serial_rw); spin_lock_init(&sc->sc_pm_lock); mutex_init(&sc->mutex); #ifdef CONFIG_ATH9K_DEBUGFS spin_lock_init(&sc->nodes_lock); INIT_LIST_HEAD(&sc->nodes); #endif 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 */ /* Initializes the hardware for all supported chipsets */ ret = ath9k_hw_init(ah); if (ret) goto err_hw; ret = ath9k_init_queues(sc); if (ret) goto err_queues; ret = ath9k_init_btcoex(sc); if (ret) goto err_btcoex; ret = ath9k_init_channels_rates(sc); if (ret) goto err_btcoex; ath9k_init_crypto(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_hw_deinit(ah); err_hw: kfree(ah); sc->sc_ah = NULL; return ret; }
static int ath9k_init_softc(u16 devid, struct ath_softc *sc, const struct ath_bus_ops *bus_ops) { struct ath_hw *ah = NULL; struct ath9k_hw_capabilities *pCap; struct ath_common *common; int ret = 0, i; int csz = 0; ah = devm_kzalloc(sc->dev, sizeof(struct ath_hw), GFP_KERNEL); if (!ah) return -ENOMEM; ah->dev = sc->dev; ah->hw = sc->hw; ah->hw_version.devid = devid; ah->ah_flags |= AH_USE_EEPROM; ah->led_pin = -1; ah->reg_ops.read = ath9k_ioread32; ah->reg_ops.multi_read = ath9k_multi_ioread32; ah->reg_ops.write = ath9k_iowrite32; ah->reg_ops.rmw = ath9k_reg_rmw; pCap = &ah->caps; common = ath9k_hw_common(ah); /* Will be cleared in ath9k_start() */ set_bit(ATH_OP_INVALID, &common->op_flags); sc->sc_ah = ah; sc->dfs_detector = dfs_pattern_detector_init(common, NL80211_DFS_UNSET); sc->tx99_power = MAX_RATE_POWER + 1; init_waitqueue_head(&sc->tx_wait); sc->cur_chan = &sc->chanctx[0]; if (!ath9k_is_chanctx_enabled()) sc->cur_chan->hw_queue_base = 0; common->ops = &ah->reg_ops; common->bus_ops = bus_ops; common->ps_ops = &ath9k_ps_ops; common->ah = ah; common->hw = sc->hw; common->priv = sc; common->debug_mask = ath9k_debug; common->btcoex_enabled = ath9k_btcoex_enable == 1; common->disable_ani = false; /* * Platform quirks. */ ath9k_init_pcoem_platform(sc); ret = ath9k_init_platform(sc); if (ret) return ret; ret = ath9k_of_init(sc); if (ret) return ret; if (ath9k_led_active_high != -1) ah->config.led_active_high = ath9k_led_active_high == 1; /* * Enable WLAN/BT RX Antenna diversity only when: * * - BTCOEX is disabled. * - the user manually requests the feature. * - the HW cap is set using the platform data. */ if (!common->btcoex_enabled && ath9k_bt_ant_diversity && (pCap->hw_caps & ATH9K_HW_CAP_BT_ANT_DIV)) common->bt_ant_diversity = 1; spin_lock_init(&common->cc_lock); spin_lock_init(&sc->intr_lock); spin_lock_init(&sc->sc_serial_rw); spin_lock_init(&sc->sc_pm_lock); spin_lock_init(&sc->chan_lock); mutex_init(&sc->mutex); tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc); tasklet_init(&sc->bcon_tasklet, ath9k_beacon_tasklet, (unsigned long)sc); timer_setup(&sc->sleep_timer, ath_ps_full_sleep, 0); INIT_WORK(&sc->hw_reset_work, ath_reset_work); INIT_WORK(&sc->paprd_work, ath_paprd_calibrate); INIT_DELAYED_WORK(&sc->hw_pll_work, ath_hw_pll_work); INIT_DELAYED_WORK(&sc->hw_check_work, ath_hw_check_work); ath9k_init_channel_context(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 */ /* Initializes the hardware for all supported chipsets */ ret = ath9k_hw_init(ah); if (ret) goto err_hw; ret = ath9k_init_queues(sc); if (ret) goto err_queues; ret = ath9k_init_btcoex(sc); if (ret) goto err_btcoex; ret = ath9k_cmn_init_channels_rates(common); if (ret) goto err_btcoex; ret = ath9k_init_p2p(sc); if (ret) goto err_btcoex; ath9k_cmn_init_crypto(sc->sc_ah); ath9k_init_misc(sc); ath_chanctx_init(sc); ath9k_offchannel_init(sc); if (common->bus_ops->aspm_init) common->bus_ops->aspm_init(common); 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_hw_deinit(ah); err_hw: ath9k_eeprom_release(sc); dev_kfree_skb_any(sc->tx99_skb); return ret; }
static int ath9k_init_softc(u16 devid, struct ath_softc *sc, const struct ath_bus_ops *bus_ops) { struct ath9k_platform_data *pdata = sc->dev->platform_data; struct ath_hw *ah = NULL; struct ath9k_hw_capabilities *pCap; struct ath_common *common; int ret = 0, i; int csz = 0; ah = devm_kzalloc(sc->dev, sizeof(struct ath_hw), GFP_KERNEL); if (!ah) return -ENOMEM; ah->dev = sc->dev; ah->hw = sc->hw; ah->hw_version.devid = devid; ah->reg_ops.read = ath9k_ioread32; ah->reg_ops.write = ath9k_iowrite32; ah->reg_ops.rmw = ath9k_reg_rmw; atomic_set(&ah->intr_ref_cnt, -1); sc->sc_ah = ah; pCap = &ah->caps; common = ath9k_hw_common(ah); sc->dfs_detector = dfs_pattern_detector_init(common, NL80211_DFS_UNSET); sc->tx99_power = MAX_RATE_POWER + 1; if (!pdata) { ah->ah_flags |= AH_USE_EEPROM; sc->sc_ah->led_pin = -1; } else { sc->sc_ah->gpio_mask = pdata->gpio_mask; sc->sc_ah->gpio_val = pdata->gpio_val; sc->sc_ah->led_pin = pdata->led_pin; ah->is_clk_25mhz = pdata->is_clk_25mhz; ah->get_mac_revision = pdata->get_mac_revision; ah->external_reset = pdata->external_reset; } common->ops = &ah->reg_ops; common->bus_ops = bus_ops; common->ah = ah; common->hw = sc->hw; common->priv = sc; common->debug_mask = ath9k_debug; common->btcoex_enabled = ath9k_btcoex_enable == 1; common->disable_ani = false; /* * Platform quirks. */ ath9k_init_platform(sc); /* * Enable WLAN/BT RX Antenna diversity only when: * * - BTCOEX is disabled. * - the user manually requests the feature. * - the HW cap is set using the platform data. */ if (!common->btcoex_enabled && ath9k_bt_ant_diversity && (pCap->hw_caps & ATH9K_HW_CAP_BT_ANT_DIV)) common->bt_ant_diversity = 1; spin_lock_init(&common->cc_lock); 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, ath9k_beacon_tasklet, (unsigned long)sc); 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); setup_timer(&sc->rx_poll_timer, ath_rx_poll, (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 */ if (pdata && pdata->eeprom_name) { ret = ath9k_eeprom_request(sc, pdata->eeprom_name); if (ret) return ret; } /* Initializes the hardware for all supported chipsets */ ret = ath9k_hw_init(ah); if (ret) goto err_hw; if (pdata && pdata->macaddr) memcpy(common->macaddr, pdata->macaddr, ETH_ALEN); ret = ath9k_init_queues(sc); if (ret) goto err_queues; ret = ath9k_init_btcoex(sc); if (ret) goto err_btcoex; ret = ath9k_init_channels_rates(sc); if (ret) goto err_btcoex; ath9k_cmn_init_crypto(sc->sc_ah); ath9k_init_misc(sc); ath_fill_led_pin(sc); if (common->bus_ops->aspm_init) common->bus_ops->aspm_init(common); 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_hw_deinit(ah); err_hw: ath9k_eeprom_release(sc); dev_kfree_skb_any(sc->tx99_skb); return ret; }
/* * pause the xmit traffic of a specified vap * and requeue the traffic back on to the * corresponding nodes (tid queues of nodes). * if vap is null then pause all the vaps. * handle both aggregates and non aggregate * frames. in the case of management frames * the frames are dropped (completed with error). * the caller should have paused all the nodes (tids of the nodes) * before pausing the vap. */ static void ath_tx_vap_pause_txqs(struct ath_softc *sc, struct ath_vap *avp ) { u_int32_t i; int npend = 0; struct ath_hal *ah = sc->sc_ah; u_int8_t q_needs_pause[HAL_NUM_TX_QUEUES]; int restart_after_reset=0; spin_lock(&(sc)->sc_vap_pause_lock);// This lock is only used for escalate irql restart: npend = 0; ath_vap_pause_set_in_progress(sc); OS_MEMZERO(q_needs_pause, sizeof(q_needs_pause)); /* * stop all the HAL data queues */ if (!sc->sc_invalid) { #ifndef ATH_SUPPORT_HTC struct ath_txq *txq=NULL; if (avp == NULL && sc->sc_fastabortenabled) { (void) ath_hal_aborttxdma(ah); for (i = 0; i < HAL_NUM_TX_QUEUES; i++) { if (ATH_TXQ_SETUP(sc, i)) { int n_q_pending=0; txq = &sc->sc_txq[i]; /* The TxDMA may not really be stopped. * Double check the hal tx pending count */ n_q_pending = ath_hal_numtxpending(ah, sc->sc_txq[i].axq_qnum); if (n_q_pending) { (void) ath_hal_stoptxdma(ah, txq->axq_qnum, 0); npend += ath_hal_numtxpending(ah, sc->sc_txq[i].axq_qnum); } } /* * at this point all Data queues are paused * all the queues need to processed and restarted. */ q_needs_pause[i] = AH_TRUE; } } else { for (i = 0; i < HAL_NUM_TX_QUEUES; i++) { if (ATH_TXQ_SETUP(sc, i)) { txq = &sc->sc_txq[i]; /* check if the queue needs to be paused */ q_needs_pause[i] = ath_tx_vap_check_txq_needs_pause(sc,txq,avp); } } (void) ath_hal_aborttxdma(ah); for (i = 0; i < HAL_NUM_TX_QUEUES; i++) { if (ATH_TXQ_SETUP(sc, i)) { int n_q_pending=0; txq = &sc->sc_txq[i]; n_q_pending = ath_hal_numtxpending(ah, sc->sc_txq[i].axq_qnum); if (n_q_pending) { npend += ath_hal_numtxpending(ah, sc->sc_txq[i].axq_qnum); } } } } #endif } if (npend && !restart_after_reset) { ath_vap_pause_clear_in_progress(sc); spin_unlock(&(sc)->sc_vap_pause_lock); #ifdef AR_DEBUG ath_dump_descriptors(sc); #endif /* TxDMA not stopped, reset the hal */ DPRINTF(sc, ATH_DEBUG_RESET, "%s: Unable to stop TxDMA. Reset HAL!\n", __func__); ath_reset_start(sc, 0, 0, 0); ath_reset(sc); ath_reset_end(sc, 0); restart_after_reset=1; spin_lock(&(sc)->sc_vap_pause_lock); goto restart; } if (npend && restart_after_reset) { /* TxDMA not stopped, reset the hal */ DPRINTF(sc, ATH_DEBUG_RESET, "%s: Unable to stop TxDMA Even after Reset, ignore and continue \n", __func__); } /* TO-DO need to handle cab queue */ /* at this point the HW xmit should have been completely stopped. */ if (sc->sc_enhanceddmasupport) { ath_tx_edma_process(sc); } for (i = 0; i < HAL_NUM_TX_QUEUES; i++) { if (q_needs_pause[i]) { #ifdef ATH_TX_BUF_FLOW_CNTL struct ath_txq *txq = &sc->sc_txq[i]; #if ATH_DEBUG == 0 /* Fix the compile error when ATH_DEBUG = 0 */ txq = txq; #endif DPRINTF(sc, ATH_DEBUG_ANY,"#####%s : %d qnum %d buf_used %d \n", __func__,__LINE__,txq->axq_qnum, txq->axq_num_buf_used ); #endif if (!sc->sc_enhanceddmasupport) { ath_tx_processq(sc, &sc->sc_txq[i]); /* process any frames that are completed */ } ath_tx_vap_pause_txq(sc, &sc->sc_txq[i], avp); #ifdef ATH_TX_BUF_FLOW_CNTL DPRINTF(sc, ATH_DEBUG_ANY,"#####%s : %d qnum %d buf_used %d \n", __func__,__LINE__,txq->axq_qnum, txq->axq_num_buf_used); #endif } } ath_vap_pause_clear_in_progress(sc); spin_unlock(&(sc)->sc_vap_pause_lock); }
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 = zalloc(sizeof(struct ath_hw)); if (!ah) return -ENOMEM; ah->dev = sc->dev; ah->hw_version.devid = devid; ah->hw_version.subsysid = subsysid; ah->reg_ops.read = ath9k_ioread32; ah->reg_ops.write = ath9k_iowrite32; ah->reg_ops.rmw = ath9k_reg_rmw; sc->sc_ah = ah; sc->hwinfo = zalloc(sizeof(*sc->hwinfo)); if (!sc->hwinfo) { DBG("ath9k: cannot allocate 802.11 hardware info structure\n"); return -ENOMEM; } ah->ah_flags |= AH_USE_EEPROM; sc->sc_ah->led_pin = -1; common = ath9k_hw_common(ah); common->ops = &ah->reg_ops; common->bus_ops = bus_ops; common->ah = ah; common->dev = sc->dev; common->priv = sc; sc->intr_tq = ath9k_tasklet; /* * 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 */ /* Initializes the hardware for all supported chipsets */ ret = ath9k_hw_init(ah); if (ret) goto err_hw; memcpy(sc->hwinfo->hwaddr, common->macaddr, ETH_ALEN); ret = ath9k_init_queues(sc); if (ret) goto err_queues; ret = ath9k_init_channels_rates(sc); if (ret) goto err_btcoex; ath9k_init_crypto(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_hw_deinit(ah); err_hw: free(sc->hwinfo); sc->hwinfo = NULL; free(ah); sc->sc_ah = NULL; return ret; }