qdio_debug.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  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: %d\n", q->last_move);
  59. seq_printf(m, "polling: %d\n", q->u.in.polling);
  60. seq_printf(m, "ack start: %d\n", q->u.in.ack_start);
  61. seq_printf(m, "ack count: %d\n", q->u.in.ack_count);
  62. seq_printf(m, "slsb buffer states:\n");
  63. seq_printf(m, "|0 |8 |16 |24 |32 |40 |48 |56 63|\n");
  64. qdio_siga_sync_q(q);
  65. for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; i++) {
  66. get_buf_state(q, i, &state, 0);
  67. switch (state) {
  68. case SLSB_P_INPUT_NOT_INIT:
  69. case SLSB_P_OUTPUT_NOT_INIT:
  70. seq_printf(m, "N");
  71. break;
  72. case SLSB_P_INPUT_PRIMED:
  73. case SLSB_CU_OUTPUT_PRIMED:
  74. seq_printf(m, "+");
  75. break;
  76. case SLSB_P_INPUT_ACK:
  77. seq_printf(m, "A");
  78. break;
  79. case SLSB_P_INPUT_ERROR:
  80. case SLSB_P_OUTPUT_ERROR:
  81. seq_printf(m, "x");
  82. break;
  83. case SLSB_CU_INPUT_EMPTY:
  84. case SLSB_P_OUTPUT_EMPTY:
  85. seq_printf(m, "-");
  86. break;
  87. case SLSB_P_INPUT_HALTED:
  88. case SLSB_P_OUTPUT_HALTED:
  89. seq_printf(m, ".");
  90. break;
  91. default:
  92. seq_printf(m, "?");
  93. }
  94. if (i == 63)
  95. seq_printf(m, "\n");
  96. }
  97. seq_printf(m, "\n");
  98. seq_printf(m, "|64 |72 |80 |88 |96 |104 |112 | 127|\n");
  99. return 0;
  100. }
  101. static ssize_t qstat_seq_write(struct file *file, const char __user *buf,
  102. size_t count, loff_t *off)
  103. {
  104. struct seq_file *seq = file->private_data;
  105. struct qdio_q *q = seq->private;
  106. if (!q)
  107. return 0;
  108. if (q->is_input_q)
  109. xchg(q->irq_ptr->dsci, 1);
  110. local_bh_disable();
  111. tasklet_schedule(&q->tasklet);
  112. local_bh_enable();
  113. return count;
  114. }
  115. static int qstat_seq_open(struct inode *inode, struct file *filp)
  116. {
  117. return single_open(filp, qstat_show,
  118. filp->f_path.dentry->d_inode->i_private);
  119. }
  120. static void remove_debugfs_entry(struct qdio_q *q)
  121. {
  122. int i;
  123. for (i = 0; i < MAX_DEBUGFS_QUEUES; i++) {
  124. if (!debugfs_queues[i])
  125. continue;
  126. if (debugfs_queues[i]->d_inode->i_private == q) {
  127. debugfs_remove(debugfs_queues[i]);
  128. debugfs_queues[i] = NULL;
  129. }
  130. }
  131. }
  132. static struct file_operations debugfs_fops = {
  133. .owner = THIS_MODULE,
  134. .open = qstat_seq_open,
  135. .read = seq_read,
  136. .write = qstat_seq_write,
  137. .llseek = seq_lseek,
  138. .release = single_release,
  139. };
  140. static void setup_debugfs_entry(struct qdio_q *q, struct ccw_device *cdev)
  141. {
  142. int i = 0;
  143. char name[QDIO_DEBUGFS_NAME_LEN];
  144. while (debugfs_queues[i] != NULL) {
  145. i++;
  146. if (i >= MAX_DEBUGFS_QUEUES)
  147. return;
  148. }
  149. snprintf(name, QDIO_DEBUGFS_NAME_LEN, "%s_%s_%d",
  150. dev_name(&cdev->dev),
  151. q->is_input_q ? "input" : "output",
  152. q->nr);
  153. debugfs_queues[i] = debugfs_create_file(name, S_IFREG | S_IRUGO | S_IWUSR,
  154. debugfs_root, q, &debugfs_fops);
  155. if (IS_ERR(debugfs_queues[i]))
  156. debugfs_queues[i] = NULL;
  157. }
  158. void qdio_setup_debug_entries(struct qdio_irq *irq_ptr, struct ccw_device *cdev)
  159. {
  160. struct qdio_q *q;
  161. int i;
  162. mutex_lock(&debugfs_mutex);
  163. for_each_input_queue(irq_ptr, q, i)
  164. setup_debugfs_entry(q, cdev);
  165. for_each_output_queue(irq_ptr, q, i)
  166. setup_debugfs_entry(q, cdev);
  167. mutex_unlock(&debugfs_mutex);
  168. }
  169. void qdio_shutdown_debug_entries(struct qdio_irq *irq_ptr, struct ccw_device *cdev)
  170. {
  171. struct qdio_q *q;
  172. int i;
  173. mutex_lock(&debugfs_mutex);
  174. for_each_input_queue(irq_ptr, q, i)
  175. remove_debugfs_entry(q);
  176. for_each_output_queue(irq_ptr, q, i)
  177. remove_debugfs_entry(q);
  178. mutex_unlock(&debugfs_mutex);
  179. }
  180. int __init qdio_debug_init(void)
  181. {
  182. debugfs_root = debugfs_create_dir("qdio_queues", NULL);
  183. qdio_dbf_setup = debug_register("qdio_setup", 16, 1, 16);
  184. debug_register_view(qdio_dbf_setup, &debug_hex_ascii_view);
  185. debug_set_level(qdio_dbf_setup, DBF_INFO);
  186. DBF_EVENT("dbf created\n");
  187. qdio_dbf_error = debug_register("qdio_error", 4, 1, 16);
  188. debug_register_view(qdio_dbf_error, &debug_hex_ascii_view);
  189. debug_set_level(qdio_dbf_error, DBF_INFO);
  190. DBF_ERROR("dbf created\n");
  191. return 0;
  192. }
  193. void qdio_debug_exit(void)
  194. {
  195. debugfs_remove(debugfs_root);
  196. if (qdio_dbf_setup)
  197. debug_unregister(qdio_dbf_setup);
  198. if (qdio_dbf_error)
  199. debug_unregister(qdio_dbf_error);
  200. }