static int ath9k_tx99_init(struct ath_softc *sc) { struct ieee80211_hw *hw = sc->hw; struct ath_hw *ah = sc->sc_ah; struct ath_common *common = ath9k_hw_common(ah); struct ath_tx_control txctl; int r; if (test_bit(ATH_OP_INVALID, &common->op_flags)) { ath_err(common, "driver is in invalid state unable to use TX99"); return -EINVAL; } sc->tx99_skb = ath9k_build_tx99_skb(sc); if (!sc->tx99_skb) return -ENOMEM; memset(&txctl, 0, sizeof(txctl)); txctl.txq = sc->tx.txq_map[IEEE80211_AC_VO]; ath_reset(sc, NULL); ath9k_ps_wakeup(sc); ath9k_hw_disable_interrupts(ah); atomic_set(&ah->intr_ref_cnt, -1); ath_drain_all_txq(sc); ath_stoprecv(sc); sc->tx99_state = true; ieee80211_stop_queues(hw); if (sc->tx99_power == MAX_RATE_POWER + 1) sc->tx99_power = MAX_RATE_POWER; ath9k_hw_tx99_set_txpower(ah, sc->tx99_power); r = ath9k_tx99_send(sc, sc->tx99_skb, &txctl); if (r) { ath_dbg(common, XMIT, "Failed to xmit TX99 skb\n"); return r; } ath_dbg(common, XMIT, "TX99 xmit started using %d ( %ddBm)\n", sc->tx99_power, sc->tx99_power / 2); /* We leave the harware awake as it will be chugging on */ return 0; }
static ssize_t write_file_tx99_power(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { struct ath_softc *sc = file->private_data; int r; u8 tx_power; r = kstrtou8_from_user(user_buf, count, 0, &tx_power); if (r) return r; if (tx_power > MAX_RATE_POWER) return -EINVAL; sc->tx99_power = tx_power; ath9k_ps_wakeup(sc); ath9k_hw_tx99_set_txpower(sc->sc_ah, sc->tx99_power); ath9k_ps_restore(sc); return count; }