diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-debugfs.c | 181 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-trans.c | 243 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-trans.h | 12 |
3 files changed, 258 insertions, 178 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 0aa84560dc2d..d3223214a801 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c | |||
@@ -882,178 +882,6 @@ DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40); | |||
882 | DEBUGFS_READ_WRITE_FILE_OPS(sleep_level_override); | 882 | DEBUGFS_READ_WRITE_FILE_OPS(sleep_level_override); |
883 | DEBUGFS_READ_FILE_OPS(current_sleep_command); | 883 | DEBUGFS_READ_FILE_OPS(current_sleep_command); |
884 | 884 | ||
885 | static ssize_t iwl_dbgfs_traffic_log_read(struct file *file, | ||
886 | char __user *user_buf, | ||
887 | size_t count, loff_t *ppos) | ||
888 | { | ||
889 | struct iwl_priv *priv = file->private_data; | ||
890 | int pos = 0, ofs = 0; | ||
891 | int cnt = 0, entry; | ||
892 | struct iwl_tx_queue *txq; | ||
893 | struct iwl_queue *q; | ||
894 | struct iwl_rx_queue *rxq = &priv->rxq; | ||
895 | char *buf; | ||
896 | int bufsz = ((IWL_TRAFFIC_ENTRIES * IWL_TRAFFIC_ENTRY_SIZE * 64) * 2) + | ||
897 | (priv->cfg->base_params->num_of_queues * 32 * 8) + 400; | ||
898 | const u8 *ptr; | ||
899 | ssize_t ret; | ||
900 | |||
901 | if (!priv->txq) { | ||
902 | IWL_ERR(priv, "txq not ready\n"); | ||
903 | return -EAGAIN; | ||
904 | } | ||
905 | buf = kzalloc(bufsz, GFP_KERNEL); | ||
906 | if (!buf) { | ||
907 | IWL_ERR(priv, "Can not allocate buffer\n"); | ||
908 | return -ENOMEM; | ||
909 | } | ||
910 | pos += scnprintf(buf + pos, bufsz - pos, "Tx Queue\n"); | ||
911 | for (cnt = 0; cnt < hw_params(priv).max_txq_num; cnt++) { | ||
912 | txq = &priv->txq[cnt]; | ||
913 | q = &txq->q; | ||
914 | pos += scnprintf(buf + pos, bufsz - pos, | ||
915 | "q[%d]: read_ptr: %u, write_ptr: %u\n", | ||
916 | cnt, q->read_ptr, q->write_ptr); | ||
917 | } | ||
918 | if (priv->tx_traffic && | ||
919 | (iwl_get_debug_level(priv->shrd) & IWL_DL_TX)) { | ||
920 | ptr = priv->tx_traffic; | ||
921 | pos += scnprintf(buf + pos, bufsz - pos, | ||
922 | "Tx Traffic idx: %u\n", priv->tx_traffic_idx); | ||
923 | for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) { | ||
924 | for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16; | ||
925 | entry++, ofs += 16) { | ||
926 | pos += scnprintf(buf + pos, bufsz - pos, | ||
927 | "0x%.4x ", ofs); | ||
928 | hex_dump_to_buffer(ptr + ofs, 16, 16, 2, | ||
929 | buf + pos, bufsz - pos, 0); | ||
930 | pos += strlen(buf + pos); | ||
931 | if (bufsz - pos > 0) | ||
932 | buf[pos++] = '\n'; | ||
933 | } | ||
934 | } | ||
935 | } | ||
936 | |||
937 | pos += scnprintf(buf + pos, bufsz - pos, "Rx Queue\n"); | ||
938 | pos += scnprintf(buf + pos, bufsz - pos, | ||
939 | "read: %u, write: %u\n", | ||
940 | rxq->read, rxq->write); | ||
941 | |||
942 | if (priv->rx_traffic && | ||
943 | (iwl_get_debug_level(priv->shrd) & IWL_DL_RX)) { | ||
944 | ptr = priv->rx_traffic; | ||
945 | pos += scnprintf(buf + pos, bufsz - pos, | ||
946 | "Rx Traffic idx: %u\n", priv->rx_traffic_idx); | ||
947 | for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) { | ||
948 | for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16; | ||
949 | entry++, ofs += 16) { | ||
950 | pos += scnprintf(buf + pos, bufsz - pos, | ||
951 | "0x%.4x ", ofs); | ||
952 | hex_dump_to_buffer(ptr + ofs, 16, 16, 2, | ||
953 | buf + pos, bufsz - pos, 0); | ||
954 | pos += strlen(buf + pos); | ||
955 | if (bufsz - pos > 0) | ||
956 | buf[pos++] = '\n'; | ||
957 | } | ||
958 | } | ||
959 | } | ||
960 | |||
961 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
962 | kfree(buf); | ||
963 | return ret; | ||
964 | } | ||
965 | |||
966 | static ssize_t iwl_dbgfs_traffic_log_write(struct file *file, | ||
967 | const char __user *user_buf, | ||
968 | size_t count, loff_t *ppos) | ||
969 | { | ||
970 | struct iwl_priv *priv = file->private_data; | ||
971 | char buf[8]; | ||
972 | int buf_size; | ||
973 | int traffic_log; | ||
974 | |||
975 | memset(buf, 0, sizeof(buf)); | ||
976 | buf_size = min(count, sizeof(buf) - 1); | ||
977 | if (copy_from_user(buf, user_buf, buf_size)) | ||
978 | return -EFAULT; | ||
979 | if (sscanf(buf, "%d", &traffic_log) != 1) | ||
980 | return -EFAULT; | ||
981 | if (traffic_log == 0) | ||
982 | iwl_reset_traffic_log(priv); | ||
983 | |||
984 | return count; | ||
985 | } | ||
986 | |||
987 | static ssize_t iwl_dbgfs_tx_queue_read(struct file *file, | ||
988 | char __user *user_buf, | ||
989 | size_t count, loff_t *ppos) { | ||
990 | |||
991 | struct iwl_priv *priv = file->private_data; | ||
992 | struct iwl_tx_queue *txq; | ||
993 | struct iwl_queue *q; | ||
994 | char *buf; | ||
995 | int pos = 0; | ||
996 | int cnt; | ||
997 | int ret; | ||
998 | const size_t bufsz = sizeof(char) * 64 * | ||
999 | priv->cfg->base_params->num_of_queues; | ||
1000 | |||
1001 | if (!priv->txq) { | ||
1002 | IWL_ERR(priv, "txq not ready\n"); | ||
1003 | return -EAGAIN; | ||
1004 | } | ||
1005 | buf = kzalloc(bufsz, GFP_KERNEL); | ||
1006 | if (!buf) | ||
1007 | return -ENOMEM; | ||
1008 | |||
1009 | for (cnt = 0; cnt < hw_params(priv).max_txq_num; cnt++) { | ||
1010 | txq = &priv->txq[cnt]; | ||
1011 | q = &txq->q; | ||
1012 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1013 | "hwq %.2d: read=%u write=%u stop=%d" | ||
1014 | " swq_id=%#.2x (ac %d/hwq %d)\n", | ||
1015 | cnt, q->read_ptr, q->write_ptr, | ||
1016 | !!test_bit(cnt, priv->queue_stopped), | ||
1017 | txq->swq_id, txq->swq_id & 3, | ||
1018 | (txq->swq_id >> 2) & 0x1f); | ||
1019 | if (cnt >= 4) | ||
1020 | continue; | ||
1021 | /* for the ACs, display the stop count too */ | ||
1022 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1023 | " stop-count: %d\n", | ||
1024 | atomic_read(&priv->queue_stop_count[cnt])); | ||
1025 | } | ||
1026 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
1027 | kfree(buf); | ||
1028 | return ret; | ||
1029 | } | ||
1030 | |||
1031 | static ssize_t iwl_dbgfs_rx_queue_read(struct file *file, | ||
1032 | char __user *user_buf, | ||
1033 | size_t count, loff_t *ppos) { | ||
1034 | |||
1035 | struct iwl_priv *priv = file->private_data; | ||
1036 | struct iwl_rx_queue *rxq = &priv->rxq; | ||
1037 | char buf[256]; | ||
1038 | int pos = 0; | ||
1039 | const size_t bufsz = sizeof(buf); | ||
1040 | |||
1041 | pos += scnprintf(buf + pos, bufsz - pos, "read: %u\n", | ||
1042 | rxq->read); | ||
1043 | pos += scnprintf(buf + pos, bufsz - pos, "write: %u\n", | ||
1044 | rxq->write); | ||
1045 | pos += scnprintf(buf + pos, bufsz - pos, "free_count: %u\n", | ||
1046 | rxq->free_count); | ||
1047 | if (rxq->rb_stts) { | ||
1048 | pos += scnprintf(buf + pos, bufsz - pos, "closed_rb_num: %u\n", | ||
1049 | le16_to_cpu(rxq->rb_stts->closed_rb_num) & 0x0FFF); | ||
1050 | } else { | ||
1051 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1052 | "closed_rb_num: Not Allocated\n"); | ||
1053 | } | ||
1054 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
1055 | } | ||
1056 | |||
1057 | static const char *fmt_value = " %-30s %10u\n"; | 885 | static const char *fmt_value = " %-30s %10u\n"; |
1058 | static const char *fmt_hex = " %-30s 0x%02X\n"; | 886 | static const char *fmt_hex = " %-30s 0x%02X\n"; |
1059 | static const char *fmt_table = " %-30s %10u %10u %10u %10u\n"; | 887 | static const char *fmt_table = " %-30s %10u %10u %10u %10u\n"; |
@@ -2630,9 +2458,6 @@ static ssize_t iwl_dbgfs_protection_mode_write(struct file *file, | |||
2630 | 2458 | ||
2631 | DEBUGFS_READ_FILE_OPS(rx_statistics); | 2459 | DEBUGFS_READ_FILE_OPS(rx_statistics); |
2632 | DEBUGFS_READ_FILE_OPS(tx_statistics); | 2460 | DEBUGFS_READ_FILE_OPS(tx_statistics); |
2633 | DEBUGFS_READ_WRITE_FILE_OPS(traffic_log); | ||
2634 | DEBUGFS_READ_FILE_OPS(rx_queue); | ||
2635 | DEBUGFS_READ_FILE_OPS(tx_queue); | ||
2636 | DEBUGFS_READ_FILE_OPS(ucode_rx_stats); | 2461 | DEBUGFS_READ_FILE_OPS(ucode_rx_stats); |
2637 | DEBUGFS_READ_FILE_OPS(ucode_tx_stats); | 2462 | DEBUGFS_READ_FILE_OPS(ucode_tx_stats); |
2638 | DEBUGFS_READ_FILE_OPS(ucode_general_stats); | 2463 | DEBUGFS_READ_FILE_OPS(ucode_general_stats); |
@@ -2696,9 +2521,6 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) | |||
2696 | DEBUGFS_ADD_FILE(disable_ht40, dir_data, S_IWUSR | S_IRUSR); | 2521 | DEBUGFS_ADD_FILE(disable_ht40, dir_data, S_IWUSR | S_IRUSR); |
2697 | DEBUGFS_ADD_FILE(rx_statistics, dir_debug, S_IRUSR); | 2522 | DEBUGFS_ADD_FILE(rx_statistics, dir_debug, S_IRUSR); |
2698 | DEBUGFS_ADD_FILE(tx_statistics, dir_debug, S_IRUSR); | 2523 | DEBUGFS_ADD_FILE(tx_statistics, dir_debug, S_IRUSR); |
2699 | DEBUGFS_ADD_FILE(traffic_log, dir_debug, S_IWUSR | S_IRUSR); | ||
2700 | DEBUGFS_ADD_FILE(rx_queue, dir_debug, S_IRUSR); | ||
2701 | DEBUGFS_ADD_FILE(tx_queue, dir_debug, S_IRUSR); | ||
2702 | DEBUGFS_ADD_FILE(power_save_status, dir_debug, S_IRUSR); | 2524 | DEBUGFS_ADD_FILE(power_save_status, dir_debug, S_IRUSR); |
2703 | DEBUGFS_ADD_FILE(clear_ucode_statistics, dir_debug, S_IWUSR); | 2525 | DEBUGFS_ADD_FILE(clear_ucode_statistics, dir_debug, S_IWUSR); |
2704 | DEBUGFS_ADD_FILE(clear_traffic_statistics, dir_debug, S_IWUSR); | 2526 | DEBUGFS_ADD_FILE(clear_traffic_statistics, dir_debug, S_IWUSR); |
@@ -2727,6 +2549,9 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) | |||
2727 | &priv->disable_sens_cal); | 2549 | &priv->disable_sens_cal); |
2728 | DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf, | 2550 | DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf, |
2729 | &priv->disable_chain_noise_cal); | 2551 | &priv->disable_chain_noise_cal); |
2552 | |||
2553 | if (iwl_trans_dbgfs_register(trans(priv), dir_debug)) | ||
2554 | goto err; | ||
2730 | return 0; | 2555 | return 0; |
2731 | 2556 | ||
2732 | err: | 2557 | err: |
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index 739087f3025c..eeeb1304eb37 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c | |||
@@ -61,6 +61,7 @@ | |||
61 | * | 61 | * |
62 | *****************************************************************************/ | 62 | *****************************************************************************/ |
63 | #include <linux/interrupt.h> | 63 | #include <linux/interrupt.h> |
64 | #include <linux/debugfs.h> | ||
64 | 65 | ||
65 | #include "iwl-dev.h" | 66 | #include "iwl-dev.h" |
66 | #include "iwl-trans.h" | 67 | #include "iwl-trans.h" |
@@ -1169,6 +1170,246 @@ static struct iwl_trans *iwl_trans_pcie_alloc(struct iwl_shared *shrd) | |||
1169 | return iwl_trans; | 1170 | return iwl_trans; |
1170 | } | 1171 | } |
1171 | 1172 | ||
1173 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
1174 | /* create and remove of files */ | ||
1175 | #define DEBUGFS_ADD_FILE(name, parent, mode) do { \ | ||
1176 | if (!debugfs_create_file(#name, mode, parent, priv, \ | ||
1177 | &iwl_dbgfs_##name##_ops)) \ | ||
1178 | return -ENOMEM; \ | ||
1179 | } while (0) | ||
1180 | |||
1181 | /* file operation */ | ||
1182 | #define DEBUGFS_READ_FUNC(name) \ | ||
1183 | static ssize_t iwl_dbgfs_##name##_read(struct file *file, \ | ||
1184 | char __user *user_buf, \ | ||
1185 | size_t count, loff_t *ppos); | ||
1186 | |||
1187 | #define DEBUGFS_WRITE_FUNC(name) \ | ||
1188 | static ssize_t iwl_dbgfs_##name##_write(struct file *file, \ | ||
1189 | const char __user *user_buf, \ | ||
1190 | size_t count, loff_t *ppos); | ||
1191 | |||
1192 | |||
1193 | static int iwl_dbgfs_open_file_generic(struct inode *inode, struct file *file) | ||
1194 | { | ||
1195 | file->private_data = inode->i_private; | ||
1196 | return 0; | ||
1197 | } | ||
1198 | |||
1199 | #define DEBUGFS_READ_FILE_OPS(name) \ | ||
1200 | DEBUGFS_READ_FUNC(name); \ | ||
1201 | static const struct file_operations iwl_dbgfs_##name##_ops = { \ | ||
1202 | .read = iwl_dbgfs_##name##_read, \ | ||
1203 | .open = iwl_dbgfs_open_file_generic, \ | ||
1204 | .llseek = generic_file_llseek, \ | ||
1205 | }; | ||
1206 | |||
1207 | #define DEBUGFS_READ_WRITE_FILE_OPS(name) \ | ||
1208 | DEBUGFS_READ_FUNC(name); \ | ||
1209 | DEBUGFS_WRITE_FUNC(name); \ | ||
1210 | static const struct file_operations iwl_dbgfs_##name##_ops = { \ | ||
1211 | .write = iwl_dbgfs_##name##_write, \ | ||
1212 | .read = iwl_dbgfs_##name##_read, \ | ||
1213 | .open = iwl_dbgfs_open_file_generic, \ | ||
1214 | .llseek = generic_file_llseek, \ | ||
1215 | }; | ||
1216 | |||
1217 | static ssize_t iwl_dbgfs_traffic_log_read(struct file *file, | ||
1218 | char __user *user_buf, | ||
1219 | size_t count, loff_t *ppos) | ||
1220 | { | ||
1221 | struct iwl_priv *priv = file->private_data; | ||
1222 | int pos = 0, ofs = 0; | ||
1223 | int cnt = 0, entry; | ||
1224 | struct iwl_tx_queue *txq; | ||
1225 | struct iwl_queue *q; | ||
1226 | struct iwl_rx_queue *rxq = &priv->rxq; | ||
1227 | char *buf; | ||
1228 | int bufsz = ((IWL_TRAFFIC_ENTRIES * IWL_TRAFFIC_ENTRY_SIZE * 64) * 2) + | ||
1229 | (priv->cfg->base_params->num_of_queues * 32 * 8) + 400; | ||
1230 | const u8 *ptr; | ||
1231 | ssize_t ret; | ||
1232 | |||
1233 | if (!priv->txq) { | ||
1234 | IWL_ERR(priv, "txq not ready\n"); | ||
1235 | return -EAGAIN; | ||
1236 | } | ||
1237 | buf = kzalloc(bufsz, GFP_KERNEL); | ||
1238 | if (!buf) { | ||
1239 | IWL_ERR(priv, "Can not allocate buffer\n"); | ||
1240 | return -ENOMEM; | ||
1241 | } | ||
1242 | pos += scnprintf(buf + pos, bufsz - pos, "Tx Queue\n"); | ||
1243 | for (cnt = 0; cnt < hw_params(priv).max_txq_num; cnt++) { | ||
1244 | txq = &priv->txq[cnt]; | ||
1245 | q = &txq->q; | ||
1246 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1247 | "q[%d]: read_ptr: %u, write_ptr: %u\n", | ||
1248 | cnt, q->read_ptr, q->write_ptr); | ||
1249 | } | ||
1250 | if (priv->tx_traffic && | ||
1251 | (iwl_get_debug_level(priv->shrd) & IWL_DL_TX)) { | ||
1252 | ptr = priv->tx_traffic; | ||
1253 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1254 | "Tx Traffic idx: %u\n", priv->tx_traffic_idx); | ||
1255 | for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) { | ||
1256 | for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16; | ||
1257 | entry++, ofs += 16) { | ||
1258 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1259 | "0x%.4x ", ofs); | ||
1260 | hex_dump_to_buffer(ptr + ofs, 16, 16, 2, | ||
1261 | buf + pos, bufsz - pos, 0); | ||
1262 | pos += strlen(buf + pos); | ||
1263 | if (bufsz - pos > 0) | ||
1264 | buf[pos++] = '\n'; | ||
1265 | } | ||
1266 | } | ||
1267 | } | ||
1268 | |||
1269 | pos += scnprintf(buf + pos, bufsz - pos, "Rx Queue\n"); | ||
1270 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1271 | "read: %u, write: %u\n", | ||
1272 | rxq->read, rxq->write); | ||
1273 | |||
1274 | if (priv->rx_traffic && | ||
1275 | (iwl_get_debug_level(priv->shrd) & IWL_DL_RX)) { | ||
1276 | ptr = priv->rx_traffic; | ||
1277 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1278 | "Rx Traffic idx: %u\n", priv->rx_traffic_idx); | ||
1279 | for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) { | ||
1280 | for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16; | ||
1281 | entry++, ofs += 16) { | ||
1282 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1283 | "0x%.4x ", ofs); | ||
1284 | hex_dump_to_buffer(ptr + ofs, 16, 16, 2, | ||
1285 | buf + pos, bufsz - pos, 0); | ||
1286 | pos += strlen(buf + pos); | ||
1287 | if (bufsz - pos > 0) | ||
1288 | buf[pos++] = '\n'; | ||
1289 | } | ||
1290 | } | ||
1291 | } | ||
1292 | |||
1293 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
1294 | kfree(buf); | ||
1295 | return ret; | ||
1296 | } | ||
1297 | |||
1298 | static ssize_t iwl_dbgfs_traffic_log_write(struct file *file, | ||
1299 | const char __user *user_buf, | ||
1300 | size_t count, loff_t *ppos) | ||
1301 | { | ||
1302 | struct iwl_priv *priv = file->private_data; | ||
1303 | char buf[8]; | ||
1304 | int buf_size; | ||
1305 | int traffic_log; | ||
1306 | |||
1307 | memset(buf, 0, sizeof(buf)); | ||
1308 | buf_size = min(count, sizeof(buf) - 1); | ||
1309 | if (copy_from_user(buf, user_buf, buf_size)) | ||
1310 | return -EFAULT; | ||
1311 | if (sscanf(buf, "%d", &traffic_log) != 1) | ||
1312 | return -EFAULT; | ||
1313 | if (traffic_log == 0) | ||
1314 | iwl_reset_traffic_log(priv); | ||
1315 | |||
1316 | return count; | ||
1317 | } | ||
1318 | |||
1319 | static ssize_t iwl_dbgfs_tx_queue_read(struct file *file, | ||
1320 | char __user *user_buf, | ||
1321 | size_t count, loff_t *ppos) { | ||
1322 | |||
1323 | struct iwl_priv *priv = file->private_data; | ||
1324 | struct iwl_tx_queue *txq; | ||
1325 | struct iwl_queue *q; | ||
1326 | char *buf; | ||
1327 | int pos = 0; | ||
1328 | int cnt; | ||
1329 | int ret; | ||
1330 | const size_t bufsz = sizeof(char) * 64 * | ||
1331 | priv->cfg->base_params->num_of_queues; | ||
1332 | |||
1333 | if (!priv->txq) { | ||
1334 | IWL_ERR(priv, "txq not ready\n"); | ||
1335 | return -EAGAIN; | ||
1336 | } | ||
1337 | buf = kzalloc(bufsz, GFP_KERNEL); | ||
1338 | if (!buf) | ||
1339 | return -ENOMEM; | ||
1340 | |||
1341 | for (cnt = 0; cnt < hw_params(priv).max_txq_num; cnt++) { | ||
1342 | txq = &priv->txq[cnt]; | ||
1343 | q = &txq->q; | ||
1344 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1345 | "hwq %.2d: read=%u write=%u stop=%d" | ||
1346 | " swq_id=%#.2x (ac %d/hwq %d)\n", | ||
1347 | cnt, q->read_ptr, q->write_ptr, | ||
1348 | !!test_bit(cnt, priv->queue_stopped), | ||
1349 | txq->swq_id, txq->swq_id & 3, | ||
1350 | (txq->swq_id >> 2) & 0x1f); | ||
1351 | if (cnt >= 4) | ||
1352 | continue; | ||
1353 | /* for the ACs, display the stop count too */ | ||
1354 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1355 | " stop-count: %d\n", | ||
1356 | atomic_read(&priv->queue_stop_count[cnt])); | ||
1357 | } | ||
1358 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
1359 | kfree(buf); | ||
1360 | return ret; | ||
1361 | } | ||
1362 | |||
1363 | static ssize_t iwl_dbgfs_rx_queue_read(struct file *file, | ||
1364 | char __user *user_buf, | ||
1365 | size_t count, loff_t *ppos) { | ||
1366 | struct iwl_priv *priv = file->private_data; | ||
1367 | struct iwl_rx_queue *rxq = &priv->rxq; | ||
1368 | char buf[256]; | ||
1369 | int pos = 0; | ||
1370 | const size_t bufsz = sizeof(buf); | ||
1371 | |||
1372 | pos += scnprintf(buf + pos, bufsz - pos, "read: %u\n", | ||
1373 | rxq->read); | ||
1374 | pos += scnprintf(buf + pos, bufsz - pos, "write: %u\n", | ||
1375 | rxq->write); | ||
1376 | pos += scnprintf(buf + pos, bufsz - pos, "free_count: %u\n", | ||
1377 | rxq->free_count); | ||
1378 | if (rxq->rb_stts) { | ||
1379 | pos += scnprintf(buf + pos, bufsz - pos, "closed_rb_num: %u\n", | ||
1380 | le16_to_cpu(rxq->rb_stts->closed_rb_num) & 0x0FFF); | ||
1381 | } else { | ||
1382 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1383 | "closed_rb_num: Not Allocated\n"); | ||
1384 | } | ||
1385 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
1386 | } | ||
1387 | |||
1388 | DEBUGFS_READ_WRITE_FILE_OPS(traffic_log); | ||
1389 | DEBUGFS_READ_FILE_OPS(rx_queue); | ||
1390 | DEBUGFS_READ_FILE_OPS(tx_queue); | ||
1391 | |||
1392 | /* | ||
1393 | * Create the debugfs files and directories | ||
1394 | * | ||
1395 | */ | ||
1396 | static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans, | ||
1397 | struct dentry *dir) | ||
1398 | { | ||
1399 | struct iwl_priv *priv = priv(trans); | ||
1400 | |||
1401 | DEBUGFS_ADD_FILE(traffic_log, dir, S_IWUSR | S_IRUSR); | ||
1402 | DEBUGFS_ADD_FILE(rx_queue, dir, S_IRUSR); | ||
1403 | DEBUGFS_ADD_FILE(tx_queue, dir, S_IRUSR); | ||
1404 | return 0; | ||
1405 | } | ||
1406 | #else | ||
1407 | static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans, | ||
1408 | struct dentry *dir) | ||
1409 | { return 0; } | ||
1410 | |||
1411 | #endif /*CONFIG_IWLWIFI_DEBUGFS */ | ||
1412 | |||
1172 | const struct iwl_trans_ops trans_ops_pcie = { | 1413 | const struct iwl_trans_ops trans_ops_pcie = { |
1173 | .alloc = iwl_trans_pcie_alloc, | 1414 | .alloc = iwl_trans_pcie_alloc, |
1174 | .request_irq = iwl_trans_pcie_request_irq, | 1415 | .request_irq = iwl_trans_pcie_request_irq, |
@@ -1194,5 +1435,7 @@ const struct iwl_trans_ops trans_ops_pcie = { | |||
1194 | 1435 | ||
1195 | .sync_irq = iwl_trans_pcie_sync_irq, | 1436 | .sync_irq = iwl_trans_pcie_sync_irq, |
1196 | .free = iwl_trans_pcie_free, | 1437 | .free = iwl_trans_pcie_free, |
1438 | |||
1439 | .dbgfs_register = iwl_trans_pcie_dbgfs_register, | ||
1197 | }; | 1440 | }; |
1198 | 1441 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 4a0c7867cb6e..a9b3157994e9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h | |||
@@ -63,6 +63,8 @@ | |||
63 | #ifndef __iwl_trans_h__ | 63 | #ifndef __iwl_trans_h__ |
64 | #define __iwl_trans_h__ | 64 | #define __iwl_trans_h__ |
65 | 65 | ||
66 | #include <linux/debugfs.h> | ||
67 | |||
66 | /*This file includes the declaration that are exported from the transport | 68 | /*This file includes the declaration that are exported from the transport |
67 | * layer */ | 69 | * layer */ |
68 | 70 | ||
@@ -98,6 +100,8 @@ struct iwl_shared; | |||
98 | * layer shall not pass any Rx. | 100 | * layer shall not pass any Rx. |
99 | * @free: release all the ressource for the transport layer itself such as | 101 | * @free: release all the ressource for the transport layer itself such as |
100 | * irq, tasklet etc... | 102 | * irq, tasklet etc... |
103 | * @dbgfs_register: add the dbgfs files under this directory. Files will be | ||
104 | * automatically deleted. | ||
101 | */ | 105 | */ |
102 | struct iwl_trans_ops { | 106 | struct iwl_trans_ops { |
103 | 107 | ||
@@ -128,6 +132,8 @@ struct iwl_trans_ops { | |||
128 | 132 | ||
129 | void (*sync_irq)(struct iwl_priv *priv); | 133 | void (*sync_irq)(struct iwl_priv *priv); |
130 | void (*free)(struct iwl_priv *priv); | 134 | void (*free)(struct iwl_priv *priv); |
135 | |||
136 | int (*dbgfs_register)(struct iwl_trans *trans, struct dentry* dir); | ||
131 | }; | 137 | }; |
132 | 138 | ||
133 | /** | 139 | /** |
@@ -232,6 +238,12 @@ static inline void iwl_trans_free(struct iwl_trans *trans) | |||
232 | trans->ops->free(priv(trans)); | 238 | trans->ops->free(priv(trans)); |
233 | } | 239 | } |
234 | 240 | ||
241 | static inline int iwl_trans_dbgfs_register(struct iwl_trans *trans, | ||
242 | struct dentry *dir) | ||
243 | { | ||
244 | return trans->ops->dbgfs_register(trans, dir); | ||
245 | } | ||
246 | |||
235 | /***************************************************** | 247 | /***************************************************** |
236 | * Transport layers implementations | 248 | * Transport layers implementations |
237 | ******************************************************/ | 249 | ******************************************************/ |