debugfs_sta.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  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. #include "core.h"
  17. #include "wmi-ops.h"
  18. #include "debug.h"
  19. static void ath10k_sta_update_extd_stats_rx_duration(struct ath10k *ar,
  20. struct ath10k_fw_stats *stats)
  21. {
  22. struct ath10k_fw_extd_stats_peer *peer;
  23. struct ieee80211_sta *sta;
  24. struct ath10k_sta *arsta;
  25. rcu_read_lock();
  26. list_for_each_entry(peer, &stats->peers_extd, list) {
  27. sta = ieee80211_find_sta_by_ifaddr(ar->hw, peer->peer_macaddr,
  28. NULL);
  29. if (!sta)
  30. continue;
  31. arsta = (struct ath10k_sta *)sta->drv_priv;
  32. arsta->rx_duration += (u64)peer->rx_duration;
  33. }
  34. rcu_read_unlock();
  35. }
  36. static void ath10k_sta_update_stats_rx_duration(struct ath10k *ar,
  37. struct ath10k_fw_stats *stats)
  38. {
  39. struct ath10k_fw_stats_peer *peer;
  40. struct ieee80211_sta *sta;
  41. struct ath10k_sta *arsta;
  42. rcu_read_lock();
  43. list_for_each_entry(peer, &stats->peers, list) {
  44. sta = ieee80211_find_sta_by_ifaddr(ar->hw, peer->peer_macaddr,
  45. NULL);
  46. if (!sta)
  47. continue;
  48. arsta = (struct ath10k_sta *)sta->drv_priv;
  49. arsta->rx_duration += (u64)peer->rx_duration;
  50. }
  51. rcu_read_unlock();
  52. }
  53. void ath10k_sta_update_rx_duration(struct ath10k *ar,
  54. struct ath10k_fw_stats *stats)
  55. {
  56. if (stats->extended)
  57. ath10k_sta_update_extd_stats_rx_duration(ar, stats);
  58. else
  59. ath10k_sta_update_stats_rx_duration(ar, stats);
  60. }
  61. void ath10k_sta_statistics(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
  62. struct ieee80211_sta *sta,
  63. struct station_info *sinfo)
  64. {
  65. struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
  66. struct ath10k *ar = arsta->arvif->ar;
  67. if (!ath10k_peer_stats_enabled(ar))
  68. return;
  69. sinfo->rx_duration = arsta->rx_duration;
  70. sinfo->filled |= 1ULL << NL80211_STA_INFO_RX_DURATION;
  71. if (!arsta->txrate.legacy && !arsta->txrate.nss)
  72. return;
  73. if (arsta->txrate.legacy) {
  74. sinfo->txrate.legacy = arsta->txrate.legacy;
  75. } else {
  76. sinfo->txrate.mcs = arsta->txrate.mcs;
  77. sinfo->txrate.nss = arsta->txrate.nss;
  78. sinfo->txrate.bw = arsta->txrate.bw;
  79. }
  80. sinfo->txrate.flags = arsta->txrate.flags;
  81. sinfo->filled |= 1ULL << NL80211_STA_INFO_TX_BITRATE;
  82. }
  83. static ssize_t ath10k_dbg_sta_read_aggr_mode(struct file *file,
  84. char __user *user_buf,
  85. size_t count, loff_t *ppos)
  86. {
  87. struct ieee80211_sta *sta = file->private_data;
  88. struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
  89. struct ath10k *ar = arsta->arvif->ar;
  90. char buf[32];
  91. int len = 0;
  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. return simple_read_from_buffer(user_buf, count, ppos, buf, len);
  98. }
  99. static ssize_t ath10k_dbg_sta_write_aggr_mode(struct file *file,
  100. const char __user *user_buf,
  101. size_t count, loff_t *ppos)
  102. {
  103. struct ieee80211_sta *sta = file->private_data;
  104. struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
  105. struct ath10k *ar = arsta->arvif->ar;
  106. u32 aggr_mode;
  107. int ret;
  108. if (kstrtouint_from_user(user_buf, count, 0, &aggr_mode))
  109. return -EINVAL;
  110. if (aggr_mode >= ATH10K_DBG_AGGR_MODE_MAX)
  111. return -EINVAL;
  112. mutex_lock(&ar->conf_mutex);
  113. if ((ar->state != ATH10K_STATE_ON) ||
  114. (aggr_mode == arsta->aggr_mode)) {
  115. ret = count;
  116. goto out;
  117. }
  118. ret = ath10k_wmi_addba_clear_resp(ar, arsta->arvif->vdev_id, sta->addr);
  119. if (ret) {
  120. ath10k_warn(ar, "failed to clear addba session ret: %d\n", ret);
  121. goto out;
  122. }
  123. arsta->aggr_mode = aggr_mode;
  124. out:
  125. mutex_unlock(&ar->conf_mutex);
  126. return ret;
  127. }
  128. static const struct file_operations fops_aggr_mode = {
  129. .read = ath10k_dbg_sta_read_aggr_mode,
  130. .write = ath10k_dbg_sta_write_aggr_mode,
  131. .open = simple_open,
  132. .owner = THIS_MODULE,
  133. .llseek = default_llseek,
  134. };
  135. static ssize_t ath10k_dbg_sta_write_addba(struct file *file,
  136. const char __user *user_buf,
  137. size_t count, loff_t *ppos)
  138. {
  139. struct ieee80211_sta *sta = file->private_data;
  140. struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
  141. struct ath10k *ar = arsta->arvif->ar;
  142. u32 tid, buf_size;
  143. int ret;
  144. char buf[64];
  145. simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
  146. /* make sure that buf is null terminated */
  147. buf[sizeof(buf) - 1] = '\0';
  148. ret = sscanf(buf, "%u %u", &tid, &buf_size);
  149. if (ret != 2)
  150. return -EINVAL;
  151. /* Valid TID values are 0 through 15 */
  152. if (tid > HTT_DATA_TX_EXT_TID_MGMT - 2)
  153. return -EINVAL;
  154. mutex_lock(&ar->conf_mutex);
  155. if ((ar->state != ATH10K_STATE_ON) ||
  156. (arsta->aggr_mode != ATH10K_DBG_AGGR_MODE_MANUAL)) {
  157. ret = count;
  158. goto out;
  159. }
  160. ret = ath10k_wmi_addba_send(ar, arsta->arvif->vdev_id, sta->addr,
  161. tid, buf_size);
  162. if (ret) {
  163. ath10k_warn(ar, "failed to send addba request: vdev_id %u peer %pM tid %u buf_size %u\n",
  164. arsta->arvif->vdev_id, sta->addr, tid, buf_size);
  165. }
  166. ret = count;
  167. out:
  168. mutex_unlock(&ar->conf_mutex);
  169. return ret;
  170. }
  171. static const struct file_operations fops_addba = {
  172. .write = ath10k_dbg_sta_write_addba,
  173. .open = simple_open,
  174. .owner = THIS_MODULE,
  175. .llseek = default_llseek,
  176. };
  177. static ssize_t ath10k_dbg_sta_write_addba_resp(struct file *file,
  178. const char __user *user_buf,
  179. size_t count, loff_t *ppos)
  180. {
  181. struct ieee80211_sta *sta = file->private_data;
  182. struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
  183. struct ath10k *ar = arsta->arvif->ar;
  184. u32 tid, status;
  185. int ret;
  186. char buf[64];
  187. simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
  188. /* make sure that buf is null terminated */
  189. buf[sizeof(buf) - 1] = '\0';
  190. ret = sscanf(buf, "%u %u", &tid, &status);
  191. if (ret != 2)
  192. return -EINVAL;
  193. /* Valid TID values are 0 through 15 */
  194. if (tid > HTT_DATA_TX_EXT_TID_MGMT - 2)
  195. return -EINVAL;
  196. mutex_lock(&ar->conf_mutex);
  197. if ((ar->state != ATH10K_STATE_ON) ||
  198. (arsta->aggr_mode != ATH10K_DBG_AGGR_MODE_MANUAL)) {
  199. ret = count;
  200. goto out;
  201. }
  202. ret = ath10k_wmi_addba_set_resp(ar, arsta->arvif->vdev_id, sta->addr,
  203. tid, status);
  204. if (ret) {
  205. ath10k_warn(ar, "failed to send addba response: vdev_id %u peer %pM tid %u status%u\n",
  206. arsta->arvif->vdev_id, sta->addr, tid, status);
  207. }
  208. ret = count;
  209. out:
  210. mutex_unlock(&ar->conf_mutex);
  211. return ret;
  212. }
  213. static const struct file_operations fops_addba_resp = {
  214. .write = ath10k_dbg_sta_write_addba_resp,
  215. .open = simple_open,
  216. .owner = THIS_MODULE,
  217. .llseek = default_llseek,
  218. };
  219. static ssize_t ath10k_dbg_sta_write_delba(struct file *file,
  220. const char __user *user_buf,
  221. size_t count, loff_t *ppos)
  222. {
  223. struct ieee80211_sta *sta = file->private_data;
  224. struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
  225. struct ath10k *ar = arsta->arvif->ar;
  226. u32 tid, initiator, reason;
  227. int ret;
  228. char buf[64];
  229. simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
  230. /* make sure that buf is null terminated */
  231. buf[sizeof(buf) - 1] = '\0';
  232. ret = sscanf(buf, "%u %u %u", &tid, &initiator, &reason);
  233. if (ret != 3)
  234. return -EINVAL;
  235. /* Valid TID values are 0 through 15 */
  236. if (tid > HTT_DATA_TX_EXT_TID_MGMT - 2)
  237. return -EINVAL;
  238. mutex_lock(&ar->conf_mutex);
  239. if ((ar->state != ATH10K_STATE_ON) ||
  240. (arsta->aggr_mode != ATH10K_DBG_AGGR_MODE_MANUAL)) {
  241. ret = count;
  242. goto out;
  243. }
  244. ret = ath10k_wmi_delba_send(ar, arsta->arvif->vdev_id, sta->addr,
  245. tid, initiator, reason);
  246. if (ret) {
  247. ath10k_warn(ar, "failed to send delba: vdev_id %u peer %pM tid %u initiator %u reason %u\n",
  248. arsta->arvif->vdev_id, sta->addr, tid, initiator,
  249. reason);
  250. }
  251. ret = count;
  252. out:
  253. mutex_unlock(&ar->conf_mutex);
  254. return ret;
  255. }
  256. static const struct file_operations fops_delba = {
  257. .write = ath10k_dbg_sta_write_delba,
  258. .open = simple_open,
  259. .owner = THIS_MODULE,
  260. .llseek = default_llseek,
  261. };
  262. void ath10k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
  263. struct ieee80211_sta *sta, struct dentry *dir)
  264. {
  265. debugfs_create_file("aggr_mode", S_IRUGO | S_IWUSR, dir, sta,
  266. &fops_aggr_mode);
  267. debugfs_create_file("addba", S_IWUSR, dir, sta, &fops_addba);
  268. debugfs_create_file("addba_resp", S_IWUSR, dir, sta, &fops_addba_resp);
  269. debugfs_create_file("delba", S_IWUSR, dir, sta, &fops_delba);
  270. }