umc-bus.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. /*
  2. * Bus for UWB Multi-interface Controller capabilities.
  3. *
  4. * Copyright (C) 2007 Cambridge Silicon Radio Ltd.
  5. *
  6. * This file is released under the GNU GPL v2.
  7. */
  8. #include <linux/kernel.h>
  9. #include <linux/sysfs.h>
  10. #include <linux/workqueue.h>
  11. #include <linux/uwb/umc.h>
  12. #include <linux/pci.h>
  13. static int umc_bus_unbind_helper(struct device *dev, void *data)
  14. {
  15. struct device *parent = data;
  16. if (dev->parent == parent && dev->driver)
  17. device_release_driver(dev);
  18. return 0;
  19. }
  20. /**
  21. * umc_controller_reset - reset the whole UMC controller
  22. * @umc: the UMC device for the radio controller.
  23. *
  24. * Drivers will be unbound from all UMC devices belonging to the
  25. * controller and then the radio controller will be rebound. The
  26. * radio controller is expected to do a full hardware reset when it is
  27. * probed.
  28. *
  29. * If this is called while a probe() or remove() is in progress it
  30. * will return -EAGAIN and not perform the reset.
  31. */
  32. int umc_controller_reset(struct umc_dev *umc)
  33. {
  34. struct device *parent = umc->dev.parent;
  35. int ret;
  36. if (down_trylock(&parent->sem))
  37. return -EAGAIN;
  38. bus_for_each_dev(&umc_bus_type, NULL, parent, umc_bus_unbind_helper);
  39. ret = device_attach(&umc->dev);
  40. if (ret == 1)
  41. ret = 0;
  42. up(&parent->sem);
  43. return ret;
  44. }
  45. EXPORT_SYMBOL_GPL(umc_controller_reset);
  46. /**
  47. * umc_match_pci_id - match a UMC driver to a UMC device's parent PCI device.
  48. * @umc_drv: umc driver with match_data pointing to a zero-terminated
  49. * table of pci_device_id's.
  50. * @umc: umc device whose parent is to be matched.
  51. */
  52. int umc_match_pci_id(struct umc_driver *umc_drv, struct umc_dev *umc)
  53. {
  54. const struct pci_device_id *id_table = umc_drv->match_data;
  55. struct pci_dev *pci;
  56. if (umc->dev.parent->bus != &pci_bus_type)
  57. return 0;
  58. pci = to_pci_dev(umc->dev.parent);
  59. return pci_match_id(id_table, pci) != NULL;
  60. }
  61. EXPORT_SYMBOL_GPL(umc_match_pci_id);
  62. static int umc_bus_rescan_helper(struct device *dev, void *data)
  63. {
  64. int ret = 0;
  65. if (!dev->driver)
  66. ret = device_attach(dev);
  67. return ret < 0 ? ret : 0;
  68. }
  69. static void umc_bus_rescan(void)
  70. {
  71. int err;
  72. /*
  73. * We can't use bus_rescan_devices() here as it deadlocks when
  74. * it tries to retake the dev->parent semaphore.
  75. */
  76. err = bus_for_each_dev(&umc_bus_type, NULL, NULL, umc_bus_rescan_helper);
  77. if (err < 0)
  78. printk(KERN_WARNING "%s: rescan of bus failed: %d\n",
  79. KBUILD_MODNAME, err);
  80. }
  81. static int umc_bus_match(struct device *dev, struct device_driver *drv)
  82. {
  83. struct umc_dev *umc = to_umc_dev(dev);
  84. struct umc_driver *umc_driver = to_umc_driver(drv);
  85. if (umc->cap_id == umc_driver->cap_id) {
  86. if (umc_driver->match)
  87. return umc_driver->match(umc_driver, umc);
  88. else
  89. return 1;
  90. }
  91. return 0;
  92. }
  93. static int umc_device_probe(struct device *dev)
  94. {
  95. struct umc_dev *umc;
  96. struct umc_driver *umc_driver;
  97. int err;
  98. umc_driver = to_umc_driver(dev->driver);
  99. umc = to_umc_dev(dev);
  100. get_device(dev);
  101. err = umc_driver->probe(umc);
  102. if (err)
  103. put_device(dev);
  104. else
  105. umc_bus_rescan();
  106. return err;
  107. }
  108. static int umc_device_remove(struct device *dev)
  109. {
  110. struct umc_dev *umc;
  111. struct umc_driver *umc_driver;
  112. umc_driver = to_umc_driver(dev->driver);
  113. umc = to_umc_dev(dev);
  114. umc_driver->remove(umc);
  115. put_device(dev);
  116. return 0;
  117. }
  118. static int umc_device_suspend(struct device *dev, pm_message_t state)
  119. {
  120. struct umc_dev *umc;
  121. struct umc_driver *umc_driver;
  122. int err = 0;
  123. umc = to_umc_dev(dev);
  124. if (dev->driver) {
  125. umc_driver = to_umc_driver(dev->driver);
  126. if (umc_driver->suspend)
  127. err = umc_driver->suspend(umc, state);
  128. }
  129. return err;
  130. }
  131. static int umc_device_resume(struct device *dev)
  132. {
  133. struct umc_dev *umc;
  134. struct umc_driver *umc_driver;
  135. int err = 0;
  136. umc = to_umc_dev(dev);
  137. if (dev->driver) {
  138. umc_driver = to_umc_driver(dev->driver);
  139. if (umc_driver->resume)
  140. err = umc_driver->resume(umc);
  141. }
  142. return err;
  143. }
  144. static ssize_t capability_id_show(struct device *dev, struct device_attribute *attr, char *buf)
  145. {
  146. struct umc_dev *umc = to_umc_dev(dev);
  147. return sprintf(buf, "0x%02x\n", umc->cap_id);
  148. }
  149. static ssize_t version_show(struct device *dev, struct device_attribute *attr, char *buf)
  150. {
  151. struct umc_dev *umc = to_umc_dev(dev);
  152. return sprintf(buf, "0x%04x\n", umc->version);
  153. }
  154. static struct device_attribute umc_dev_attrs[] = {
  155. __ATTR_RO(capability_id),
  156. __ATTR_RO(version),
  157. __ATTR_NULL,
  158. };
  159. struct bus_type umc_bus_type = {
  160. .name = "umc",
  161. .match = umc_bus_match,
  162. .probe = umc_device_probe,
  163. .remove = umc_device_remove,
  164. .suspend = umc_device_suspend,
  165. .resume = umc_device_resume,
  166. .dev_attrs = umc_dev_attrs,
  167. };
  168. EXPORT_SYMBOL_GPL(umc_bus_type);
  169. static int __init umc_bus_init(void)
  170. {
  171. return bus_register(&umc_bus_type);
  172. }
  173. module_init(umc_bus_init);
  174. static void __exit umc_bus_exit(void)
  175. {
  176. bus_unregister(&umc_bus_type);
  177. }
  178. module_exit(umc_bus_exit);
  179. MODULE_DESCRIPTION("UWB Multi-interface Controller capability bus");
  180. MODULE_AUTHOR("Cambridge Silicon Radio Ltd.");
  181. MODULE_LICENSE("GPL");