1 /* 2 * Copyright (c) 2014 Qualcomm Atheros, Inc. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 #include "core.h" 18 #include "wmi-ops.h" 19 #include "debug.h" 20 21 static void ath10k_sta_update_extd_stats_rx_duration(struct ath10k *ar, 22 struct ath10k_fw_stats *stats) 23 { 24 struct ath10k_fw_extd_stats_peer *peer; 25 struct ieee80211_sta *sta; 26 struct ath10k_sta *arsta; 27 28 rcu_read_lock(); 29 list_for_each_entry(peer, &stats->peers_extd, list) { 30 sta = ieee80211_find_sta_by_ifaddr(ar->hw, peer->peer_macaddr, 31 NULL); 32 if (!sta) 33 continue; 34 arsta = (struct ath10k_sta *)sta->drv_priv; 35 arsta->rx_duration += (u64)peer->rx_duration; 36 } 37 rcu_read_unlock(); 38 } 39 40 static void ath10k_sta_update_stats_rx_duration(struct ath10k *ar, 41 struct ath10k_fw_stats *stats) 42 { 43 struct ath10k_fw_stats_peer *peer; 44 struct ieee80211_sta *sta; 45 struct ath10k_sta *arsta; 46 47 rcu_read_lock(); 48 list_for_each_entry(peer, &stats->peers, list) { 49 sta = ieee80211_find_sta_by_ifaddr(ar->hw, peer->peer_macaddr, 50 NULL); 51 if (!sta) 52 continue; 53 arsta = (struct ath10k_sta *)sta->drv_priv; 54 arsta->rx_duration += (u64)peer->rx_duration; 55 } 56 rcu_read_unlock(); 57 } 58 59 void ath10k_sta_update_rx_duration(struct ath10k *ar, 60 struct ath10k_fw_stats *stats) 61 { 62 if (stats->extended) 63 ath10k_sta_update_extd_stats_rx_duration(ar, stats); 64 else 65 ath10k_sta_update_stats_rx_duration(ar, stats); 66 } 67 68 void ath10k_sta_statistics(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 69 struct ieee80211_sta *sta, 70 struct station_info *sinfo) 71 { 72 struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv; 73 struct ath10k *ar = arsta->arvif->ar; 74 75 if (!ath10k_peer_stats_enabled(ar)) 76 return; 77 78 sinfo->rx_duration = arsta->rx_duration; 79 sinfo->filled |= 1ULL << NL80211_STA_INFO_RX_DURATION; 80 } 81 82 static ssize_t ath10k_dbg_sta_read_aggr_mode(struct file *file, 83 char __user *user_buf, 84 size_t count, loff_t *ppos) 85 { 86 struct ieee80211_sta *sta = file->private_data; 87 struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv; 88 struct ath10k *ar = arsta->arvif->ar; 89 char buf[32]; 90 int len = 0; 91 92 mutex_lock(&ar->conf_mutex); 93 len = scnprintf(buf, sizeof(buf) - len, "aggregation mode: %s\n", 94 (arsta->aggr_mode == ATH10K_DBG_AGGR_MODE_AUTO) ? 95 "auto" : "manual"); 96 mutex_unlock(&ar->conf_mutex); 97 98 return simple_read_from_buffer(user_buf, count, ppos, buf, len); 99 } 100 101 static ssize_t ath10k_dbg_sta_write_aggr_mode(struct file *file, 102 const char __user *user_buf, 103 size_t count, loff_t *ppos) 104 { 105 struct ieee80211_sta *sta = file->private_data; 106 struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv; 107 struct ath10k *ar = arsta->arvif->ar; 108 u32 aggr_mode; 109 int ret; 110 111 if (kstrtouint_from_user(user_buf, count, 0, &aggr_mode)) 112 return -EINVAL; 113 114 if (aggr_mode >= ATH10K_DBG_AGGR_MODE_MAX) 115 return -EINVAL; 116 117 mutex_lock(&ar->conf_mutex); 118 if ((ar->state != ATH10K_STATE_ON) || 119 (aggr_mode == arsta->aggr_mode)) { 120 ret = count; 121 goto out; 122 } 123 124 ret = ath10k_wmi_addba_clear_resp(ar, arsta->arvif->vdev_id, sta->addr); 125 if (ret) { 126 ath10k_warn(ar, "failed to clear addba session ret: %d\n", ret); 127 goto out; 128 } 129 130 arsta->aggr_mode = aggr_mode; 131 out: 132 mutex_unlock(&ar->conf_mutex); 133 return ret; 134 } 135 136 static const struct file_operations fops_aggr_mode = { 137 .read = ath10k_dbg_sta_read_aggr_mode, 138 .write = ath10k_dbg_sta_write_aggr_mode, 139 .open = simple_open, 140 .owner = THIS_MODULE, 141 .llseek = default_llseek, 142 }; 143 144 static ssize_t ath10k_dbg_sta_write_addba(struct file *file, 145 const char __user *user_buf, 146 size_t count, loff_t *ppos) 147 { 148 struct ieee80211_sta *sta = file->private_data; 149 struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv; 150 struct ath10k *ar = arsta->arvif->ar; 151 u32 tid, buf_size; 152 int ret; 153 char buf[64]; 154 155 simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count); 156 157 /* make sure that buf is null terminated */ 158 buf[sizeof(buf) - 1] = '\0'; 159 160 ret = sscanf(buf, "%u %u", &tid, &buf_size); 161 if (ret != 2) 162 return -EINVAL; 163 164 /* Valid TID values are 0 through 15 */ 165 if (tid > HTT_DATA_TX_EXT_TID_MGMT - 2) 166 return -EINVAL; 167 168 mutex_lock(&ar->conf_mutex); 169 if ((ar->state != ATH10K_STATE_ON) || 170 (arsta->aggr_mode != ATH10K_DBG_AGGR_MODE_MANUAL)) { 171 ret = count; 172 goto out; 173 } 174 175 ret = ath10k_wmi_addba_send(ar, arsta->arvif->vdev_id, sta->addr, 176 tid, buf_size); 177 if (ret) { 178 ath10k_warn(ar, "failed to send addba request: vdev_id %u peer %pM tid %u buf_size %u\n", 179 arsta->arvif->vdev_id, sta->addr, tid, buf_size); 180 } 181 182 ret = count; 183 out: 184 mutex_unlock(&ar->conf_mutex); 185 return ret; 186 } 187 188 static const struct file_operations fops_addba = { 189 .write = ath10k_dbg_sta_write_addba, 190 .open = simple_open, 191 .owner = THIS_MODULE, 192 .llseek = default_llseek, 193 }; 194 195 static ssize_t ath10k_dbg_sta_write_addba_resp(struct file *file, 196 const char __user *user_buf, 197 size_t count, loff_t *ppos) 198 { 199 struct ieee80211_sta *sta = file->private_data; 200 struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv; 201 struct ath10k *ar = arsta->arvif->ar; 202 u32 tid, status; 203 int ret; 204 char buf[64]; 205 206 simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count); 207 208 /* make sure that buf is null terminated */ 209 buf[sizeof(buf) - 1] = '\0'; 210 211 ret = sscanf(buf, "%u %u", &tid, &status); 212 if (ret != 2) 213 return -EINVAL; 214 215 /* Valid TID values are 0 through 15 */ 216 if (tid > HTT_DATA_TX_EXT_TID_MGMT - 2) 217 return -EINVAL; 218 219 mutex_lock(&ar->conf_mutex); 220 if ((ar->state != ATH10K_STATE_ON) || 221 (arsta->aggr_mode != ATH10K_DBG_AGGR_MODE_MANUAL)) { 222 ret = count; 223 goto out; 224 } 225 226 ret = ath10k_wmi_addba_set_resp(ar, arsta->arvif->vdev_id, sta->addr, 227 tid, status); 228 if (ret) { 229 ath10k_warn(ar, "failed to send addba response: vdev_id %u peer %pM tid %u status%u\n", 230 arsta->arvif->vdev_id, sta->addr, tid, status); 231 } 232 ret = count; 233 out: 234 mutex_unlock(&ar->conf_mutex); 235 return ret; 236 } 237 238 static const struct file_operations fops_addba_resp = { 239 .write = ath10k_dbg_sta_write_addba_resp, 240 .open = simple_open, 241 .owner = THIS_MODULE, 242 .llseek = default_llseek, 243 }; 244 245 static ssize_t ath10k_dbg_sta_write_delba(struct file *file, 246 const char __user *user_buf, 247 size_t count, loff_t *ppos) 248 { 249 struct ieee80211_sta *sta = file->private_data; 250 struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv; 251 struct ath10k *ar = arsta->arvif->ar; 252 u32 tid, initiator, reason; 253 int ret; 254 char buf[64]; 255 256 simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count); 257 258 /* make sure that buf is null terminated */ 259 buf[sizeof(buf) - 1] = '\0'; 260 261 ret = sscanf(buf, "%u %u %u", &tid, &initiator, &reason); 262 if (ret != 3) 263 return -EINVAL; 264 265 /* Valid TID values are 0 through 15 */ 266 if (tid > HTT_DATA_TX_EXT_TID_MGMT - 2) 267 return -EINVAL; 268 269 mutex_lock(&ar->conf_mutex); 270 if ((ar->state != ATH10K_STATE_ON) || 271 (arsta->aggr_mode != ATH10K_DBG_AGGR_MODE_MANUAL)) { 272 ret = count; 273 goto out; 274 } 275 276 ret = ath10k_wmi_delba_send(ar, arsta->arvif->vdev_id, sta->addr, 277 tid, initiator, reason); 278 if (ret) { 279 ath10k_warn(ar, "failed to send delba: vdev_id %u peer %pM tid %u initiator %u reason %u\n", 280 arsta->arvif->vdev_id, sta->addr, tid, initiator, 281 reason); 282 } 283 ret = count; 284 out: 285 mutex_unlock(&ar->conf_mutex); 286 return ret; 287 } 288 289 static const struct file_operations fops_delba = { 290 .write = ath10k_dbg_sta_write_delba, 291 .open = simple_open, 292 .owner = THIS_MODULE, 293 .llseek = default_llseek, 294 }; 295 296 void ath10k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 297 struct ieee80211_sta *sta, struct dentry *dir) 298 { 299 debugfs_create_file("aggr_mode", S_IRUGO | S_IWUSR, dir, sta, 300 &fops_aggr_mode); 301 debugfs_create_file("addba", S_IWUSR, dir, sta, &fops_addba); 302 debugfs_create_file("addba_resp", S_IWUSR, dir, sta, &fops_addba_resp); 303 debugfs_create_file("delba", S_IWUSR, dir, sta, &fops_delba); 304 } 305