cpqphp_sysfs.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Compaq Hot Plug Controller Driver
  4. *
  5. * Copyright (C) 1995,2001 Compaq Computer Corporation
  6. * Copyright (C) 2001,2003 Greg Kroah-Hartman ([email protected])
  7. * Copyright (C) 2001 IBM Corp.
  8. *
  9. * All rights reserved.
  10. *
  11. * Send feedback to <[email protected]>
  12. *
  13. */
  14. #include <linux/module.h>
  15. #include <linux/kernel.h>
  16. #include <linux/slab.h>
  17. #include <linux/types.h>
  18. #include <linux/proc_fs.h>
  19. #include <linux/workqueue.h>
  20. #include <linux/pci.h>
  21. #include <linux/pci_hotplug.h>
  22. #include <linux/mutex.h>
  23. #include <linux/debugfs.h>
  24. #include "cpqphp.h"
  25. static DEFINE_MUTEX(cpqphp_mutex);
  26. static int show_ctrl(struct controller *ctrl, char *buf)
  27. {
  28. char *out = buf;
  29. int index;
  30. struct pci_resource *res;
  31. out += sprintf(buf, "Free resources: memory\n");
  32. index = 11;
  33. res = ctrl->mem_head;
  34. while (res && index--) {
  35. out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
  36. res = res->next;
  37. }
  38. out += sprintf(out, "Free resources: prefetchable memory\n");
  39. index = 11;
  40. res = ctrl->p_mem_head;
  41. while (res && index--) {
  42. out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
  43. res = res->next;
  44. }
  45. out += sprintf(out, "Free resources: IO\n");
  46. index = 11;
  47. res = ctrl->io_head;
  48. while (res && index--) {
  49. out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
  50. res = res->next;
  51. }
  52. out += sprintf(out, "Free resources: bus numbers\n");
  53. index = 11;
  54. res = ctrl->bus_head;
  55. while (res && index--) {
  56. out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
  57. res = res->next;
  58. }
  59. return out - buf;
  60. }
  61. static int show_dev(struct controller *ctrl, char *buf)
  62. {
  63. char *out = buf;
  64. int index;
  65. struct pci_resource *res;
  66. struct pci_func *new_slot;
  67. struct slot *slot;
  68. slot = ctrl->slot;
  69. while (slot) {
  70. new_slot = cpqhp_slot_find(slot->bus, slot->device, 0);
  71. if (!new_slot)
  72. break;
  73. out += sprintf(out, "assigned resources: memory\n");
  74. index = 11;
  75. res = new_slot->mem_head;
  76. while (res && index--) {
  77. out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
  78. res = res->next;
  79. }
  80. out += sprintf(out, "assigned resources: prefetchable memory\n");
  81. index = 11;
  82. res = new_slot->p_mem_head;
  83. while (res && index--) {
  84. out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
  85. res = res->next;
  86. }
  87. out += sprintf(out, "assigned resources: IO\n");
  88. index = 11;
  89. res = new_slot->io_head;
  90. while (res && index--) {
  91. out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
  92. res = res->next;
  93. }
  94. out += sprintf(out, "assigned resources: bus numbers\n");
  95. index = 11;
  96. res = new_slot->bus_head;
  97. while (res && index--) {
  98. out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
  99. res = res->next;
  100. }
  101. slot = slot->next;
  102. }
  103. return out - buf;
  104. }
  105. static int spew_debug_info(struct controller *ctrl, char *data, int size)
  106. {
  107. int used;
  108. used = size - show_ctrl(ctrl, data);
  109. used = (size - used) - show_dev(ctrl, &data[used]);
  110. return used;
  111. }
  112. struct ctrl_dbg {
  113. int size;
  114. char *data;
  115. struct controller *ctrl;
  116. };
  117. #define MAX_OUTPUT (4*PAGE_SIZE)
  118. static int open(struct inode *inode, struct file *file)
  119. {
  120. struct controller *ctrl = inode->i_private;
  121. struct ctrl_dbg *dbg;
  122. int retval = -ENOMEM;
  123. mutex_lock(&cpqphp_mutex);
  124. dbg = kmalloc(sizeof(*dbg), GFP_KERNEL);
  125. if (!dbg)
  126. goto exit;
  127. dbg->data = kmalloc(MAX_OUTPUT, GFP_KERNEL);
  128. if (!dbg->data) {
  129. kfree(dbg);
  130. goto exit;
  131. }
  132. dbg->size = spew_debug_info(ctrl, dbg->data, MAX_OUTPUT);
  133. file->private_data = dbg;
  134. retval = 0;
  135. exit:
  136. mutex_unlock(&cpqphp_mutex);
  137. return retval;
  138. }
  139. static loff_t lseek(struct file *file, loff_t off, int whence)
  140. {
  141. struct ctrl_dbg *dbg = file->private_data;
  142. return fixed_size_llseek(file, off, whence, dbg->size);
  143. }
  144. static ssize_t read(struct file *file, char __user *buf,
  145. size_t nbytes, loff_t *ppos)
  146. {
  147. struct ctrl_dbg *dbg = file->private_data;
  148. return simple_read_from_buffer(buf, nbytes, ppos, dbg->data, dbg->size);
  149. }
  150. static int release(struct inode *inode, struct file *file)
  151. {
  152. struct ctrl_dbg *dbg = file->private_data;
  153. kfree(dbg->data);
  154. kfree(dbg);
  155. return 0;
  156. }
  157. static const struct file_operations debug_ops = {
  158. .owner = THIS_MODULE,
  159. .open = open,
  160. .llseek = lseek,
  161. .read = read,
  162. .release = release,
  163. };
  164. static struct dentry *root;
  165. void cpqhp_initialize_debugfs(void)
  166. {
  167. if (!root)
  168. root = debugfs_create_dir("cpqhp", NULL);
  169. }
  170. void cpqhp_shutdown_debugfs(void)
  171. {
  172. debugfs_remove(root);
  173. }
  174. void cpqhp_create_debugfs_files(struct controller *ctrl)
  175. {
  176. ctrl->dentry = debugfs_create_file(dev_name(&ctrl->pci_dev->dev),
  177. S_IRUGO, root, ctrl, &debug_ops);
  178. }
  179. void cpqhp_remove_debugfs_files(struct controller *ctrl)
  180. {
  181. debugfs_remove(ctrl->dentry);
  182. ctrl->dentry = NULL;
  183. }