0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #include "ath9k.h"
0018
0019 static void ath9k_tx99_stop(struct ath_softc *sc)
0020 {
0021 struct ath_hw *ah = sc->sc_ah;
0022 struct ath_common *common = ath9k_hw_common(ah);
0023
0024 ath_drain_all_txq(sc);
0025 ath_startrecv(sc);
0026
0027 ath9k_hw_set_interrupts(ah);
0028 ath9k_hw_enable_interrupts(ah);
0029
0030 ieee80211_wake_queues(sc->hw);
0031
0032 kfree_skb(sc->tx99_skb);
0033 sc->tx99_skb = NULL;
0034 sc->tx99_state = false;
0035
0036 ath9k_hw_tx99_stop(sc->sc_ah);
0037 ath_dbg(common, XMIT, "TX99 stopped\n");
0038 }
0039
0040 static struct sk_buff *ath9k_build_tx99_skb(struct ath_softc *sc)
0041 {
0042 static u8 PN9Data[] = {0xff, 0x87, 0xb8, 0x59, 0xb7, 0xa1, 0xcc, 0x24,
0043 0x57, 0x5e, 0x4b, 0x9c, 0x0e, 0xe9, 0xea, 0x50,
0044 0x2a, 0xbe, 0xb4, 0x1b, 0xb6, 0xb0, 0x5d, 0xf1,
0045 0xe6, 0x9a, 0xe3, 0x45, 0xfd, 0x2c, 0x53, 0x18,
0046 0x0c, 0xca, 0xc9, 0xfb, 0x49, 0x37, 0xe5, 0xa8,
0047 0x51, 0x3b, 0x2f, 0x61, 0xaa, 0x72, 0x18, 0x84,
0048 0x02, 0x23, 0x23, 0xab, 0x63, 0x89, 0x51, 0xb3,
0049 0xe7, 0x8b, 0x72, 0x90, 0x4c, 0xe8, 0xfb, 0xc0};
0050 u32 len = 1200;
0051 struct ieee80211_tx_rate *rate;
0052 struct ieee80211_hw *hw = sc->hw;
0053 struct ath_hw *ah = sc->sc_ah;
0054 struct ieee80211_hdr *hdr;
0055 struct ieee80211_tx_info *tx_info;
0056 struct sk_buff *skb;
0057 struct ath_vif *avp;
0058
0059 skb = alloc_skb(len, GFP_KERNEL);
0060 if (!skb)
0061 return NULL;
0062
0063 skb_put(skb, len);
0064
0065 memset(skb->data, 0, len);
0066
0067 hdr = (struct ieee80211_hdr *)skb->data;
0068 hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA);
0069 hdr->duration_id = 0;
0070
0071 memcpy(hdr->addr1, hw->wiphy->perm_addr, ETH_ALEN);
0072 memcpy(hdr->addr2, hw->wiphy->perm_addr, ETH_ALEN);
0073 memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN);
0074
0075 if (sc->tx99_vif) {
0076 avp = (struct ath_vif *) sc->tx99_vif->drv_priv;
0077 hdr->seq_ctrl |= cpu_to_le16(avp->seq_no);
0078 }
0079
0080 tx_info = IEEE80211_SKB_CB(skb);
0081 memset(tx_info, 0, sizeof(*tx_info));
0082 rate = &tx_info->control.rates[0];
0083 tx_info->band = sc->cur_chan->chandef.chan->band;
0084 tx_info->flags = IEEE80211_TX_CTL_NO_ACK;
0085 tx_info->control.vif = sc->tx99_vif;
0086 rate->count = 1;
0087 if (ah->curchan && IS_CHAN_HT(ah->curchan)) {
0088 rate->flags |= IEEE80211_TX_RC_MCS;
0089 if (IS_CHAN_HT40(ah->curchan))
0090 rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
0091 }
0092
0093 memcpy(skb->data + sizeof(*hdr), PN9Data, sizeof(PN9Data));
0094
0095 return skb;
0096 }
0097
0098 static void ath9k_tx99_deinit(struct ath_softc *sc)
0099 {
0100 ath_reset(sc, NULL);
0101
0102 ath9k_ps_wakeup(sc);
0103 ath9k_tx99_stop(sc);
0104 ath9k_ps_restore(sc);
0105 }
0106
0107 static int ath9k_tx99_init(struct ath_softc *sc)
0108 {
0109 struct ieee80211_hw *hw = sc->hw;
0110 struct ath_hw *ah = sc->sc_ah;
0111 struct ath_common *common = ath9k_hw_common(ah);
0112 struct ath_tx_control txctl;
0113 int r;
0114
0115 if (test_bit(ATH_OP_INVALID, &common->op_flags)) {
0116 ath_err(common,
0117 "driver is in invalid state unable to use TX99");
0118 return -EINVAL;
0119 }
0120
0121 sc->tx99_skb = ath9k_build_tx99_skb(sc);
0122 if (!sc->tx99_skb)
0123 return -ENOMEM;
0124
0125 memset(&txctl, 0, sizeof(txctl));
0126 txctl.txq = sc->tx.txq_map[IEEE80211_AC_VO];
0127
0128 ath_reset(sc, NULL);
0129
0130 ath9k_ps_wakeup(sc);
0131
0132 ath9k_hw_disable_interrupts(ah);
0133 ath_drain_all_txq(sc);
0134 ath_stoprecv(sc);
0135
0136 sc->tx99_state = true;
0137
0138 ieee80211_stop_queues(hw);
0139
0140 if (sc->tx99_power == MAX_RATE_POWER + 1)
0141 sc->tx99_power = MAX_RATE_POWER;
0142
0143 ath9k_hw_tx99_set_txpower(ah, sc->tx99_power);
0144 r = ath9k_tx99_send(sc, sc->tx99_skb, &txctl);
0145 if (r) {
0146 ath_dbg(common, XMIT, "Failed to xmit TX99 skb\n");
0147 return r;
0148 }
0149
0150 ath_dbg(common, XMIT, "TX99 xmit started using %d ( %ddBm)\n",
0151 sc->tx99_power,
0152 sc->tx99_power / 2);
0153
0154
0155
0156 return 0;
0157 }
0158
0159 static ssize_t read_file_tx99(struct file *file, char __user *user_buf,
0160 size_t count, loff_t *ppos)
0161 {
0162 struct ath_softc *sc = file->private_data;
0163 char buf[3];
0164 unsigned int len;
0165
0166 len = sprintf(buf, "%d\n", sc->tx99_state);
0167 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
0168 }
0169
0170 static ssize_t write_file_tx99(struct file *file, const char __user *user_buf,
0171 size_t count, loff_t *ppos)
0172 {
0173 struct ath_softc *sc = file->private_data;
0174 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
0175 char buf[32];
0176 bool start;
0177 ssize_t len;
0178 int r;
0179
0180 if (count < 1)
0181 return -EINVAL;
0182
0183 if (sc->cur_chan->nvifs > 1)
0184 return -EOPNOTSUPP;
0185
0186 len = min(count, sizeof(buf) - 1);
0187 if (copy_from_user(buf, user_buf, len))
0188 return -EFAULT;
0189
0190 buf[len] = '\0';
0191
0192 if (strtobool(buf, &start))
0193 return -EINVAL;
0194
0195 mutex_lock(&sc->mutex);
0196
0197 if (start == sc->tx99_state) {
0198 if (!start)
0199 goto out;
0200 ath_dbg(common, XMIT, "Resetting TX99\n");
0201 ath9k_tx99_deinit(sc);
0202 }
0203
0204 if (!start) {
0205 ath9k_tx99_deinit(sc);
0206 goto out;
0207 }
0208
0209 r = ath9k_tx99_init(sc);
0210 if (r) {
0211 mutex_unlock(&sc->mutex);
0212 return r;
0213 }
0214 out:
0215 mutex_unlock(&sc->mutex);
0216 return count;
0217 }
0218
0219 static const struct file_operations fops_tx99 = {
0220 .read = read_file_tx99,
0221 .write = write_file_tx99,
0222 .open = simple_open,
0223 .owner = THIS_MODULE,
0224 .llseek = default_llseek,
0225 };
0226
0227 static ssize_t read_file_tx99_power(struct file *file,
0228 char __user *user_buf,
0229 size_t count, loff_t *ppos)
0230 {
0231 struct ath_softc *sc = file->private_data;
0232 char buf[32];
0233 unsigned int len;
0234
0235 len = sprintf(buf, "%d (%d dBm)\n",
0236 sc->tx99_power,
0237 sc->tx99_power / 2);
0238
0239 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
0240 }
0241
0242 static ssize_t write_file_tx99_power(struct file *file,
0243 const char __user *user_buf,
0244 size_t count, loff_t *ppos)
0245 {
0246 struct ath_softc *sc = file->private_data;
0247 int r;
0248 u8 tx_power;
0249
0250 r = kstrtou8_from_user(user_buf, count, 0, &tx_power);
0251 if (r)
0252 return r;
0253
0254 if (tx_power > MAX_RATE_POWER)
0255 return -EINVAL;
0256
0257 sc->tx99_power = tx_power;
0258
0259 ath9k_ps_wakeup(sc);
0260 ath9k_hw_tx99_set_txpower(sc->sc_ah, sc->tx99_power);
0261 ath9k_ps_restore(sc);
0262
0263 return count;
0264 }
0265
0266 static const struct file_operations fops_tx99_power = {
0267 .read = read_file_tx99_power,
0268 .write = write_file_tx99_power,
0269 .open = simple_open,
0270 .owner = THIS_MODULE,
0271 .llseek = default_llseek,
0272 };
0273
0274 void ath9k_tx99_init_debug(struct ath_softc *sc)
0275 {
0276 if (!AR_SREV_9280_20_OR_LATER(sc->sc_ah))
0277 return;
0278
0279 debugfs_create_file("tx99", 0600,
0280 sc->debug.debugfs_phy, sc,
0281 &fops_tx99);
0282 debugfs_create_file("tx99_power", 0600,
0283 sc->debug.debugfs_phy, sc,
0284 &fops_tx99_power);
0285 }