qdio_debug.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. /*
  2. * drivers/s390/cio/qdio_debug.c
  3. *
  4. * Copyright IBM Corp. 2008
  5. *
  6. * Author: Jan Glauber (jang@linux.vnet.ibm.com)
  7. */
  8. #include <linux/proc_fs.h>
  9. #include <linux/seq_file.h>
  10. #include <linux/debugfs.h>
  11. #include <asm/qdio.h>
  12. #include <asm/debug.h>
  13. #include "qdio_debug.h"
  14. #include "qdio.h"
  15. debug_info_t *qdio_dbf_setup;
  16. debug_info_t *qdio_dbf_error;
  17. static struct dentry *debugfs_root;
  18. #define MAX_DEBUGFS_QUEUES 32
  19. static struct dentry *debugfs_queues[MAX_DEBUGFS_QUEUES] = { NULL };
  20. static DEFINE_MUTEX(debugfs_mutex);
  21. #define QDIO_DEBUGFS_NAME_LEN 40
  22. void qdio_allocate_dbf(struct qdio_initialize *init_data,
  23. struct qdio_irq *irq_ptr)
  24. {
  25. char text[20];
  26. DBF_EVENT("qfmt:%1d", init_data->q_format);
  27. DBF_HEX(init_data->adapter_name, 8);
  28. DBF_EVENT("qpff%4x", init_data->qib_param_field_format);
  29. DBF_HEX(&init_data->qib_param_field, sizeof(void *));
  30. DBF_HEX(&init_data->input_slib_elements, sizeof(void *));
  31. DBF_HEX(&init_data->output_slib_elements, sizeof(void *));
  32. DBF_EVENT("niq:%1d noq:%1d", init_data->no_input_qs,
  33. init_data->no_output_qs);
  34. DBF_HEX(&init_data->input_handler, sizeof(void *));
  35. DBF_HEX(&init_data->output_handler, sizeof(void *));
  36. DBF_HEX(&init_data->int_parm, sizeof(long));
  37. DBF_HEX(&init_data->flags, sizeof(long));
  38. DBF_HEX(&init_data->input_sbal_addr_array, sizeof(void *));
  39. DBF_HEX(&init_data->output_sbal_addr_array, sizeof(void *));
  40. DBF_EVENT("irq:%8lx", (unsigned long)irq_ptr);
  41. /* allocate trace view for the interface */
  42. snprintf(text, 20, "qdio_%s", dev_name(&init_data->cdev->dev));
  43. irq_ptr->debug_area = debug_register(text, 2, 1, 16);
  44. debug_register_view(irq_ptr->debug_area, &debug_hex_ascii_view);
  45. debug_set_level(irq_ptr->debug_area, DBF_WARN);
  46. DBF_DEV_EVENT(DBF_ERR, irq_ptr, "dbf created");
  47. }
  48. static int qstat_show(struct seq_file *m, void *v)
  49. {
  50. unsigned char state;
  51. struct qdio_q *q = m->private;
  52. int i;
  53. if (!q)
  54. return 0;
  55. seq_printf(m, "device state indicator: %d\n", *(u32 *)q->irq_ptr->dsci);
  56. seq_printf(m, "nr_used: %d\n", atomic_read(&q->nr_buf_used));
  57. seq_printf(m, "ftc: %d\n", q->first_to_check);
  58. seq_printf(m, "last_move_ftc: %d\n", q->last_move_ftc);
  59. seq_printf(m, "polling: %d\n", q->u.in.polling);
  60. seq_printf(m, "ack count: %d\n", q->u.in.ack_count);
  61. seq_printf(m, "slsb buffer states:\n");
  62. seq_printf(m, "|0 |8 |16 |24 |32 |40 |48 |56 63|\n");
  63. qdio_siga_sync_q(q);
  64. for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; i++) {
  65. get_buf_state(q, i, &state, 0);
  66. switch (state) {
  67. case SLSB_P_INPUT_NOT_INIT:
  68. case SLSB_P_OUTPUT_NOT_INIT:
  69. seq_printf(m, "N");
  70. break;
  71. case SLSB_P_INPUT_PRIMED:
  72. case SLSB_CU_OUTPUT_PRIMED:
  73. seq_printf(m, "+");
  74. break;
  75. case SLSB_P_INPUT_ACK:
  76. seq_printf(m, "A");
  77. break;
  78. case SLSB_P_INPUT_ERROR:
  79. case SLSB_P_OUTPUT_ERROR:
  80. seq_printf(m, "x");
  81. break;
  82. case SLSB_CU_INPUT_EMPTY:
  83. case SLSB_P_OUTPUT_EMPTY:
  84. seq_printf(m, "-");
  85. break;
  86. case SLSB_P_INPUT_HALTED:
  87. case SLSB_P_OUTPUT_HALTED:
  88. seq_printf(m, ".");
  89. break;
  90. default:
  91. seq_printf(m, "?");
  92. }
  93. if (i == 63)
  94. seq_printf(m, "\n");
  95. }
  96. seq_printf(m, "\n");
  97. seq_printf(m, "|64 |72 |80 |88 |96 |104 |112 | 127|\n");
  98. return 0;
  99. }
  100. static ssize_t qstat_seq_write(struct file *file, const char __user *buf,
  101. size_t count, loff_t *off)
  102. {
  103. struct seq_file *seq = file->private_data;
  104. struct qdio_q *q = seq->private;
  105. if (!q)
  106. return 0;
  107. if (q->is_input_q)
  108. xchg(q->irq_ptr->dsci, 1);
  109. local_bh_disable();
  110. tasklet_schedule(&q->tasklet);
  111. local_bh_enable();
  112. return count;
  113. }
  114. static int qstat_seq_open(struct inode *inode, struct file *filp)
  115. {
  116. return single_open(filp, qstat_show,
  117. filp->f_path.dentry->d_inode->i_private);
  118. }
  119. static void remove_debugfs_entry(struct qdio_q *q)
  120. {
  121. int i;
  122. for (i = 0; i < MAX_DEBUGFS_QUEUES; i++) {
  123. if (!debugfs_queues[i])
  124. continue;
  125. if (debugfs_queues[i]->d_inode->i_private == q) {
  126. debugfs_remove(debugfs_queues[i]);
  127. debugfs_queues[i] = NULL;
  128. }
  129. }
  130. }
  131. static struct file_operations debugfs_fops = {
  132. .owner = THIS_MODULE,
  133. .open = qstat_seq_open,
  134. .read = seq_read,
  135. .write = qstat_seq_write,
  136. .llseek = seq_lseek,
  137. .release = single_release,
  138. };
  139. static void setup_debugfs_entry(struct qdio_q *q, struct ccw_device *cdev)
  140. {
  141. int i = 0;
  142. char name[QDIO_DEBUGFS_NAME_LEN];
  143. while (debugfs_queues[i] != NULL) {
  144. i++;
  145. if (i >= MAX_DEBUGFS_QUEUES)
  146. return;
  147. }
  148. snprintf(name, QDIO_DEBUGFS_NAME_LEN, "%s_%s_%d",
  149. dev_name(&cdev->dev),
  150. q->is_input_q ? "input" : "output",
  151. q->nr);
  152. debugfs_queues[i] = debugfs_create_file(name, S_IFREG | S_IRUGO | S_IWUSR,
  153. debugfs_root, q, &debugfs_fops);
  154. }
  155. void qdio_setup_debug_entries(struct qdio_irq *irq_ptr, struct ccw_device *cdev)
  156. {
  157. struct qdio_q *q;
  158. int i;
  159. mutex_lock(&debugfs_mutex);
  160. for_each_input_queue(irq_ptr, q, i)
  161. setup_debugfs_entry(q, cdev);
  162. for_each_output_queue(irq_ptr, q, i)
  163. setup_debugfs_entry(q, cdev);
  164. mutex_unlock(&debugfs_mutex);
  165. }
  166. void qdio_shutdown_debug_entries(struct qdio_irq *irq_ptr, struct ccw_device *cdev)
  167. {
  168. struct qdio_q *q;
  169. int i;
  170. mutex_lock(&debugfs_mutex);
  171. for_each_input_queue(irq_ptr, q, i)
  172. remove_debugfs_entry(q);
  173. for_each_output_queue(irq_ptr, q, i)
  174. remove_debugfs_entry(q);
  175. mutex_unlock(&debugfs_mutex);
  176. }
  177. int __init qdio_debug_init(void)
  178. {
  179. debugfs_root = debugfs_create_dir("qdio_queues", NULL);
  180. qdio_dbf_setup = debug_register("qdio_setup", 16, 1, 16);
  181. debug_register_view(qdio_dbf_setup, &debug_hex_ascii_view);
  182. debug_set_level(qdio_dbf_setup, DBF_INFO);
  183. DBF_EVENT("dbf created\n");
  184. qdio_dbf_error = debug_register("qdio_error", 4, 1, 16);
  185. debug_register_view(qdio_dbf_error, &debug_hex_ascii_view);
  186. debug_set_level(qdio_dbf_error, DBF_INFO);
  187. DBF_ERROR("dbf created\n");
  188. return 0;
  189. }
  190. void qdio_debug_exit(void)
  191. {
  192. debugfs_remove(debugfs_root);
  193. if (qdio_dbf_setup)
  194. debug_unregister(qdio_dbf_setup);
  195. if (qdio_dbf_error)
  196. debug_unregister(qdio_dbf_error);
  197. }