1ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan/* 2ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan * Copyright (c) 2013 Qualcomm Atheros, Inc. 3ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan * 4ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan * Permission to use, copy, modify, and/or distribute this software for any 5ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan * purpose with or without fee is hereby granted, provided that the above 6ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan * copyright notice and this permission notice appear in all copies. 7ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan * 8ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan */ 16ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 17ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan#include "ath9k.h" 18ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 19ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharanstatic void ath9k_tx99_stop(struct ath_softc *sc) 20ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan{ 21ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan struct ath_hw *ah = sc->sc_ah; 22ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan struct ath_common *common = ath9k_hw_common(ah); 23ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 24ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan ath_drain_all_txq(sc); 25ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan ath_startrecv(sc); 26ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 27ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan ath9k_hw_set_interrupts(ah); 28ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan ath9k_hw_enable_interrupts(ah); 29ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 30ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan ieee80211_wake_queues(sc->hw); 31ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 32ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan kfree_skb(sc->tx99_skb); 33ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan sc->tx99_skb = NULL; 34ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan sc->tx99_state = false; 35ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 36ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan ath9k_hw_tx99_stop(sc->sc_ah); 37ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan ath_dbg(common, XMIT, "TX99 stopped\n"); 38ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan} 39ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 40ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharanstatic struct sk_buff *ath9k_build_tx99_skb(struct ath_softc *sc) 41ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan{ 42ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan static u8 PN9Data[] = {0xff, 0x87, 0xb8, 0x59, 0xb7, 0xa1, 0xcc, 0x24, 43ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 0x57, 0x5e, 0x4b, 0x9c, 0x0e, 0xe9, 0xea, 0x50, 44ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 0x2a, 0xbe, 0xb4, 0x1b, 0xb6, 0xb0, 0x5d, 0xf1, 45ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 0xe6, 0x9a, 0xe3, 0x45, 0xfd, 0x2c, 0x53, 0x18, 46ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 0x0c, 0xca, 0xc9, 0xfb, 0x49, 0x37, 0xe5, 0xa8, 47ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 0x51, 0x3b, 0x2f, 0x61, 0xaa, 0x72, 0x18, 0x84, 48ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 0x02, 0x23, 0x23, 0xab, 0x63, 0x89, 0x51, 0xb3, 49ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 0xe7, 0x8b, 0x72, 0x90, 0x4c, 0xe8, 0xfb, 0xc0}; 50ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan u32 len = 1200; 5155957fb7a0b61d8ab6ff3f04e279b8fc22b738faLorenzo Bianconi struct ieee80211_tx_rate *rate; 52ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan struct ieee80211_hw *hw = sc->hw; 5355957fb7a0b61d8ab6ff3f04e279b8fc22b738faLorenzo Bianconi struct ath_hw *ah = sc->sc_ah; 54ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan struct ieee80211_hdr *hdr; 55ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan struct ieee80211_tx_info *tx_info; 56ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan struct sk_buff *skb; 57ca14405e3b25b38221d027d8970c1d74ed0b6532Sujith Manoharan struct ath_vif *avp; 58ca14405e3b25b38221d027d8970c1d74ed0b6532Sujith Manoharan 59ca14405e3b25b38221d027d8970c1d74ed0b6532Sujith Manoharan if (!sc->tx99_vif) 60ca14405e3b25b38221d027d8970c1d74ed0b6532Sujith Manoharan return NULL; 61ca14405e3b25b38221d027d8970c1d74ed0b6532Sujith Manoharan 62ca14405e3b25b38221d027d8970c1d74ed0b6532Sujith Manoharan avp = (struct ath_vif *)sc->tx99_vif->drv_priv; 63ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 64ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan skb = alloc_skb(len, GFP_KERNEL); 65ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan if (!skb) 66ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan return NULL; 67ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 68ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan skb_put(skb, len); 69ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 70ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan memset(skb->data, 0, len); 71ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 72ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan hdr = (struct ieee80211_hdr *)skb->data; 73ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA); 74ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan hdr->duration_id = 0; 75ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 76ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan memcpy(hdr->addr1, hw->wiphy->perm_addr, ETH_ALEN); 77ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan memcpy(hdr->addr2, hw->wiphy->perm_addr, ETH_ALEN); 78ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN); 79ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 80ca14405e3b25b38221d027d8970c1d74ed0b6532Sujith Manoharan hdr->seq_ctrl |= cpu_to_le16(avp->seq_no); 81ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 82ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan tx_info = IEEE80211_SKB_CB(skb); 83ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan memset(tx_info, 0, sizeof(*tx_info)); 8455957fb7a0b61d8ab6ff3f04e279b8fc22b738faLorenzo Bianconi rate = &tx_info->control.rates[0]; 853930563570d3714420a2ebe0324a917ff64e0422Felix Fietkau tx_info->band = sc->cur_chan->chandef.chan->band; 86ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan tx_info->flags = IEEE80211_TX_CTL_NO_ACK; 87ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan tx_info->control.vif = sc->tx99_vif; 8855957fb7a0b61d8ab6ff3f04e279b8fc22b738faLorenzo Bianconi rate->count = 1; 8955957fb7a0b61d8ab6ff3f04e279b8fc22b738faLorenzo Bianconi if (ah->curchan && IS_CHAN_HT(ah->curchan)) { 9055957fb7a0b61d8ab6ff3f04e279b8fc22b738faLorenzo Bianconi rate->flags |= IEEE80211_TX_RC_MCS; 9155957fb7a0b61d8ab6ff3f04e279b8fc22b738faLorenzo Bianconi if (IS_CHAN_HT40(ah->curchan)) 9255957fb7a0b61d8ab6ff3f04e279b8fc22b738faLorenzo Bianconi rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; 9355957fb7a0b61d8ab6ff3f04e279b8fc22b738faLorenzo Bianconi } 94ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 95ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan memcpy(skb->data + sizeof(*hdr), PN9Data, sizeof(PN9Data)); 96ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 97ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan return skb; 98ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan} 99ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 100ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharanstatic void ath9k_tx99_deinit(struct ath_softc *sc) 101ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan{ 102ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan ath_reset(sc); 103ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 104ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan ath9k_ps_wakeup(sc); 105ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan ath9k_tx99_stop(sc); 106ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan ath9k_ps_restore(sc); 107ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan} 108ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 109ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharanstatic int ath9k_tx99_init(struct ath_softc *sc) 110ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan{ 111ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan struct ieee80211_hw *hw = sc->hw; 112ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan struct ath_hw *ah = sc->sc_ah; 113ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan struct ath_common *common = ath9k_hw_common(ah); 114ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan struct ath_tx_control txctl; 115ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan int r; 116ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 117eefa01ddd57893c7f4482024029fec323c8e1b89Oleksij Rempel if (test_bit(ATH_OP_INVALID, &common->op_flags)) { 118ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan ath_err(common, 119ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan "driver is in invalid state unable to use TX99"); 120ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan return -EINVAL; 121ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan } 122ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 123ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan sc->tx99_skb = ath9k_build_tx99_skb(sc); 124ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan if (!sc->tx99_skb) 125ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan return -ENOMEM; 126ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 127ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan memset(&txctl, 0, sizeof(txctl)); 128ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan txctl.txq = sc->tx.txq_map[IEEE80211_AC_VO]; 129ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 130ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan ath_reset(sc); 131ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 132ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan ath9k_ps_wakeup(sc); 133ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 134ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan ath9k_hw_disable_interrupts(ah); 135ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan atomic_set(&ah->intr_ref_cnt, -1); 136ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan ath_drain_all_txq(sc); 137ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan ath_stoprecv(sc); 138ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 139ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan sc->tx99_state = true; 140ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 141ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan ieee80211_stop_queues(hw); 142ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 143ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan if (sc->tx99_power == MAX_RATE_POWER + 1) 144ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan sc->tx99_power = MAX_RATE_POWER; 145ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 146ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan ath9k_hw_tx99_set_txpower(ah, sc->tx99_power); 147ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan r = ath9k_tx99_send(sc, sc->tx99_skb, &txctl); 148ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan if (r) { 149ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan ath_dbg(common, XMIT, "Failed to xmit TX99 skb\n"); 150ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan return r; 151ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan } 152ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 153ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan ath_dbg(common, XMIT, "TX99 xmit started using %d ( %ddBm)\n", 154ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan sc->tx99_power, 155ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan sc->tx99_power / 2); 156ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 157ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan /* We leave the harware awake as it will be chugging on */ 158ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 159ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan return 0; 160ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan} 161ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 162ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharanstatic ssize_t read_file_tx99(struct file *file, char __user *user_buf, 163ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan size_t count, loff_t *ppos) 164ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan{ 165ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan struct ath_softc *sc = file->private_data; 166ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan char buf[3]; 167ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan unsigned int len; 168ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 169ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan len = sprintf(buf, "%d\n", sc->tx99_state); 170ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan return simple_read_from_buffer(user_buf, count, ppos, buf, len); 171ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan} 172ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 173ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharanstatic ssize_t write_file_tx99(struct file *file, const char __user *user_buf, 174ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan size_t count, loff_t *ppos) 175ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan{ 176ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan struct ath_softc *sc = file->private_data; 177ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan struct ath_common *common = ath9k_hw_common(sc->sc_ah); 178ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan char buf[32]; 179ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan bool start; 180ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan ssize_t len; 181ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan int r; 182ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 183ca529c9373bbcabf55a12e4225d625ee26fc8abbSujith Manoharan if (sc->cur_chan->nvifs > 1) 184ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan return -EOPNOTSUPP; 185ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 186ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan len = min(count, sizeof(buf) - 1); 187ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan if (copy_from_user(buf, user_buf, len)) 188ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan return -EFAULT; 189ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 190ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan if (strtobool(buf, &start)) 191ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan return -EINVAL; 192ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 193ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan if (start == sc->tx99_state) { 194ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan if (!start) 195ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan return count; 196ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan ath_dbg(common, XMIT, "Resetting TX99\n"); 197ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan ath9k_tx99_deinit(sc); 198ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan } 199ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 200ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan if (!start) { 201ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan ath9k_tx99_deinit(sc); 202ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan return count; 203ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan } 204ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 205ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan r = ath9k_tx99_init(sc); 206ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan if (r) 207ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan return r; 208ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 209ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan return count; 210ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan} 211ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 212ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharanstatic const struct file_operations fops_tx99 = { 213ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan .read = read_file_tx99, 214ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan .write = write_file_tx99, 215ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan .open = simple_open, 216ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan .owner = THIS_MODULE, 217ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan .llseek = default_llseek, 218ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan}; 219ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 220ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharanstatic ssize_t read_file_tx99_power(struct file *file, 221ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan char __user *user_buf, 222ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan size_t count, loff_t *ppos) 223ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan{ 224ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan struct ath_softc *sc = file->private_data; 225ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan char buf[32]; 226ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan unsigned int len; 227ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 228ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan len = sprintf(buf, "%d (%d dBm)\n", 229ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan sc->tx99_power, 230ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan sc->tx99_power / 2); 231ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 232ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan return simple_read_from_buffer(user_buf, count, ppos, buf, len); 233ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan} 234ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 235ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharanstatic ssize_t write_file_tx99_power(struct file *file, 236ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan const char __user *user_buf, 237ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan size_t count, loff_t *ppos) 238ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan{ 239ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan struct ath_softc *sc = file->private_data; 240ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan int r; 241ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan u8 tx_power; 242ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 243ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan r = kstrtou8_from_user(user_buf, count, 0, &tx_power); 244ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan if (r) 245ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan return r; 246ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 247ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan if (tx_power > MAX_RATE_POWER) 248ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan return -EINVAL; 249ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 250ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan sc->tx99_power = tx_power; 251ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 252ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan ath9k_ps_wakeup(sc); 253ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan ath9k_hw_tx99_set_txpower(sc->sc_ah, sc->tx99_power); 254ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan ath9k_ps_restore(sc); 255ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 256ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan return count; 257ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan} 258ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 259ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharanstatic const struct file_operations fops_tx99_power = { 260ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan .read = read_file_tx99_power, 261ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan .write = write_file_tx99_power, 262ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan .open = simple_open, 263ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan .owner = THIS_MODULE, 264ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan .llseek = default_llseek, 265ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan}; 266ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 267ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharanvoid ath9k_tx99_init_debug(struct ath_softc *sc) 268ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan{ 269ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan if (!AR_SREV_9300_20_OR_LATER(sc->sc_ah)) 270ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan return; 271ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan 272ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan debugfs_create_file("tx99", S_IRUSR | S_IWUSR, 273ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan sc->debug.debugfs_phy, sc, 274ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan &fops_tx99); 275ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan debugfs_create_file("tx99_power", S_IRUSR | S_IWUSR, 276ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan sc->debug.debugfs_phy, sc, 277ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan &fops_tx99_power); 278ef6b19e40f525777a0052956bf7d9a1985f74993Sujith Manoharan} 279