Exemple #1
0
/*
 * 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;
}
Exemple #3
0
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;
}
Exemple #4
0
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;
}
Exemple #6
0
/*
 * 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
}
Exemple #7
0
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);
}
Exemple #8
0
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;
}
Exemple #9
0
/*
 * 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));
}
Exemple #10
0
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;
}
Exemple #11
0
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;
}
Exemple #13
0
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;
}
Exemple #14
0
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;
}
Exemple #15
0
/*
 * 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);
}
Exemple #16
0
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;
}