[go: nahoru, domu]

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