drm_sysfs.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. /*
  2. * drm_sysfs.c - Modifications to drm_sysfs_class.c to support
  3. * extra sysfs attribute from DRM. Normal drm_sysfs_class
  4. * does not allow adding attributes.
  5. *
  6. * Copyright (c) 2004 Jon Smirl <jonsmirl@gmail.com>
  7. * Copyright (c) 2003-2004 Greg Kroah-Hartman <greg@kroah.com>
  8. * Copyright (c) 2003-2004 IBM Corp.
  9. *
  10. * This file is released under the GPLv2
  11. *
  12. */
  13. #include <linux/config.h>
  14. #include <linux/device.h>
  15. #include <linux/kdev_t.h>
  16. #include <linux/err.h>
  17. #include "drm_core.h"
  18. #include "drmP.h"
  19. struct drm_sysfs_class {
  20. struct class_device_attribute attr;
  21. struct class class;
  22. };
  23. #define to_drm_sysfs_class(d) container_of(d, struct drm_sysfs_class, class)
  24. struct simple_dev {
  25. struct list_head node;
  26. dev_t dev;
  27. struct class_device class_dev;
  28. };
  29. #define to_simple_dev(d) container_of(d, struct simple_dev, class_dev)
  30. static LIST_HEAD(simple_dev_list);
  31. static DEFINE_SPINLOCK(simple_dev_list_lock);
  32. static void release_simple_dev(struct class_device *class_dev)
  33. {
  34. struct simple_dev *s_dev = to_simple_dev(class_dev);
  35. kfree(s_dev);
  36. }
  37. static ssize_t show_dev(struct class_device *class_dev, char *buf)
  38. {
  39. struct simple_dev *s_dev = to_simple_dev(class_dev);
  40. return print_dev_t(buf, s_dev->dev);
  41. }
  42. static void drm_sysfs_class_release(struct class *class)
  43. {
  44. struct drm_sysfs_class *cs = to_drm_sysfs_class(class);
  45. kfree(cs);
  46. }
  47. /* Display the version of drm_core. This doesn't work right in current design */
  48. static ssize_t version_show(struct class *dev, char *buf)
  49. {
  50. return sprintf(buf, "%s %d.%d.%d %s\n", CORE_NAME, CORE_MAJOR,
  51. CORE_MINOR, CORE_PATCHLEVEL, CORE_DATE);
  52. }
  53. static CLASS_ATTR(version, S_IRUGO, version_show, NULL);
  54. /**
  55. * drm_sysfs_create - create a struct drm_sysfs_class structure
  56. * @owner: pointer to the module that is to "own" this struct drm_sysfs_class
  57. * @name: pointer to a string for the name of this class.
  58. *
  59. * This is used to create a struct drm_sysfs_class pointer that can then be used
  60. * in calls to drm_sysfs_device_add().
  61. *
  62. * Note, the pointer created here is to be destroyed when finished by making a
  63. * call to drm_sysfs_destroy().
  64. */
  65. struct drm_sysfs_class *drm_sysfs_create(struct module *owner, char *name)
  66. {
  67. struct drm_sysfs_class *cs;
  68. int retval;
  69. cs = kmalloc(sizeof(*cs), GFP_KERNEL);
  70. if (!cs) {
  71. retval = -ENOMEM;
  72. goto error;
  73. }
  74. memset(cs, 0x00, sizeof(*cs));
  75. cs->class.name = name;
  76. cs->class.class_release = drm_sysfs_class_release;
  77. cs->class.release = release_simple_dev;
  78. cs->attr.attr.name = "dev";
  79. cs->attr.attr.mode = S_IRUGO;
  80. cs->attr.attr.owner = owner;
  81. cs->attr.show = show_dev;
  82. cs->attr.store = NULL;
  83. retval = class_register(&cs->class);
  84. if (retval)
  85. goto error;
  86. class_create_file(&cs->class, &class_attr_version);
  87. return cs;
  88. error:
  89. kfree(cs);
  90. return ERR_PTR(retval);
  91. }
  92. /**
  93. * drm_sysfs_destroy - destroys a struct drm_sysfs_class structure
  94. * @cs: pointer to the struct drm_sysfs_class that is to be destroyed
  95. *
  96. * Note, the pointer to be destroyed must have been created with a call to
  97. * drm_sysfs_create().
  98. */
  99. void drm_sysfs_destroy(struct drm_sysfs_class *cs)
  100. {
  101. if ((cs == NULL) || (IS_ERR(cs)))
  102. return;
  103. class_unregister(&cs->class);
  104. }
  105. /**
  106. * drm_sysfs_device_add - adds a class device to sysfs for a character driver
  107. * @cs: pointer to the struct drm_sysfs_class that this device should be registered to.
  108. * @dev: the dev_t for the device to be added.
  109. * @device: a pointer to a struct device that is assiociated with this class device.
  110. * @fmt: string for the class device's name
  111. *
  112. * A struct class_device will be created in sysfs, registered to the specified
  113. * class. A "dev" file will be created, showing the dev_t for the device. The
  114. * pointer to the struct class_device will be returned from the call. Any further
  115. * sysfs files that might be required can be created using this pointer.
  116. * Note: the struct drm_sysfs_class passed to this function must have previously been
  117. * created with a call to drm_sysfs_create().
  118. */
  119. struct class_device *drm_sysfs_device_add(struct drm_sysfs_class *cs, dev_t dev,
  120. struct device *device,
  121. const char *fmt, ...)
  122. {
  123. va_list args;
  124. struct simple_dev *s_dev = NULL;
  125. int retval;
  126. if ((cs == NULL) || (IS_ERR(cs))) {
  127. retval = -ENODEV;
  128. goto error;
  129. }
  130. s_dev = kmalloc(sizeof(*s_dev), GFP_KERNEL);
  131. if (!s_dev) {
  132. retval = -ENOMEM;
  133. goto error;
  134. }
  135. memset(s_dev, 0x00, sizeof(*s_dev));
  136. s_dev->dev = dev;
  137. s_dev->class_dev.dev = device;
  138. s_dev->class_dev.class = &cs->class;
  139. va_start(args, fmt);
  140. vsnprintf(s_dev->class_dev.class_id, BUS_ID_SIZE, fmt, args);
  141. va_end(args);
  142. retval = class_device_register(&s_dev->class_dev);
  143. if (retval)
  144. goto error;
  145. class_device_create_file(&s_dev->class_dev, &cs->attr);
  146. spin_lock(&simple_dev_list_lock);
  147. list_add(&s_dev->node, &simple_dev_list);
  148. spin_unlock(&simple_dev_list_lock);
  149. return &s_dev->class_dev;
  150. error:
  151. kfree(s_dev);
  152. return ERR_PTR(retval);
  153. }
  154. /**
  155. * drm_sysfs_device_remove - removes a class device that was created with drm_sysfs_device_add()
  156. * @dev: the dev_t of the device that was previously registered.
  157. *
  158. * This call unregisters and cleans up a class device that was created with a
  159. * call to drm_sysfs_device_add()
  160. */
  161. void drm_sysfs_device_remove(dev_t dev)
  162. {
  163. struct simple_dev *s_dev = NULL;
  164. int found = 0;
  165. spin_lock(&simple_dev_list_lock);
  166. list_for_each_entry(s_dev, &simple_dev_list, node) {
  167. if (s_dev->dev == dev) {
  168. found = 1;
  169. break;
  170. }
  171. }
  172. if (found) {
  173. list_del(&s_dev->node);
  174. spin_unlock(&simple_dev_list_lock);
  175. class_device_unregister(&s_dev->class_dev);
  176. } else {
  177. spin_unlock(&simple_dev_list_lock);
  178. }
  179. }