device-remove.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. /*
  2. * Device manager
  3. *
  4. * Copyright (c) 2014 Google, Inc
  5. *
  6. * (C) Copyright 2012
  7. * Pavel Herrmann <morpheus.ibis@gmail.com>
  8. *
  9. * SPDX-License-Identifier: GPL-2.0+
  10. */
  11. #include <common.h>
  12. #include <errno.h>
  13. #include <malloc.h>
  14. #include <dm/device.h>
  15. #include <dm/device-internal.h>
  16. #include <dm/uclass.h>
  17. #include <dm/uclass-internal.h>
  18. #include <dm/util.h>
  19. /**
  20. * device_chld_unbind() - Unbind all device's children from the device
  21. *
  22. * On error, the function continues to unbind all children, and reports the
  23. * first error.
  24. *
  25. * @dev: The device that is to be stripped of its children
  26. * @return 0 on success, -ve on error
  27. */
  28. static int device_chld_unbind(struct udevice *dev)
  29. {
  30. struct udevice *pos, *n;
  31. int ret, saved_ret = 0;
  32. assert(dev);
  33. list_for_each_entry_safe(pos, n, &dev->child_head, sibling_node) {
  34. ret = device_unbind(pos);
  35. if (ret && !saved_ret)
  36. saved_ret = ret;
  37. }
  38. return saved_ret;
  39. }
  40. /**
  41. * device_chld_remove() - Stop all device's children
  42. * @dev: The device whose children are to be removed
  43. * @pre_os_remove: Flag, if this functions is called in the pre-OS stage
  44. * @return 0 on success, -ve on error
  45. */
  46. static int device_chld_remove(struct udevice *dev, uint flags)
  47. {
  48. struct udevice *pos, *n;
  49. int ret;
  50. assert(dev);
  51. list_for_each_entry_safe(pos, n, &dev->child_head, sibling_node) {
  52. ret = device_remove(pos, flags);
  53. if (ret)
  54. return ret;
  55. }
  56. return 0;
  57. }
  58. int device_unbind(struct udevice *dev)
  59. {
  60. const struct driver *drv;
  61. int ret;
  62. if (!dev)
  63. return -EINVAL;
  64. if (dev->flags & DM_FLAG_ACTIVATED)
  65. return -EINVAL;
  66. if (!(dev->flags & DM_FLAG_BOUND))
  67. return -EINVAL;
  68. drv = dev->driver;
  69. assert(drv);
  70. if (drv->unbind) {
  71. ret = drv->unbind(dev);
  72. if (ret)
  73. return ret;
  74. }
  75. ret = device_chld_unbind(dev);
  76. if (ret)
  77. return ret;
  78. if (dev->flags & DM_FLAG_ALLOC_PDATA) {
  79. free(dev->platdata);
  80. dev->platdata = NULL;
  81. }
  82. if (dev->flags & DM_FLAG_ALLOC_UCLASS_PDATA) {
  83. free(dev->uclass_platdata);
  84. dev->uclass_platdata = NULL;
  85. }
  86. if (dev->flags & DM_FLAG_ALLOC_PARENT_PDATA) {
  87. free(dev->parent_platdata);
  88. dev->parent_platdata = NULL;
  89. }
  90. ret = uclass_unbind_device(dev);
  91. if (ret)
  92. return ret;
  93. if (dev->parent)
  94. list_del(&dev->sibling_node);
  95. devres_release_all(dev);
  96. if (dev->flags & DM_FLAG_NAME_ALLOCED)
  97. free((char *)dev->name);
  98. free(dev);
  99. return 0;
  100. }
  101. /**
  102. * device_free() - Free memory buffers allocated by a device
  103. * @dev: Device that is to be started
  104. */
  105. void device_free(struct udevice *dev)
  106. {
  107. int size;
  108. if (dev->driver->priv_auto_alloc_size) {
  109. free(dev->priv);
  110. dev->priv = NULL;
  111. }
  112. size = dev->uclass->uc_drv->per_device_auto_alloc_size;
  113. if (size) {
  114. free(dev->uclass_priv);
  115. dev->uclass_priv = NULL;
  116. }
  117. if (dev->parent) {
  118. size = dev->parent->driver->per_child_auto_alloc_size;
  119. if (!size) {
  120. size = dev->parent->uclass->uc_drv->
  121. per_child_auto_alloc_size;
  122. }
  123. if (size) {
  124. free(dev->parent_priv);
  125. dev->parent_priv = NULL;
  126. }
  127. }
  128. devres_release_probe(dev);
  129. }
  130. static bool flags_remove(uint flags, uint drv_flags)
  131. {
  132. if ((flags & DM_REMOVE_NORMAL) ||
  133. (flags & (drv_flags & (DM_FLAG_ACTIVE_DMA | DM_FLAG_OS_PREPARE))))
  134. return true;
  135. return false;
  136. }
  137. int device_remove(struct udevice *dev, uint flags)
  138. {
  139. const struct driver *drv;
  140. int ret;
  141. if (!dev)
  142. return -EINVAL;
  143. if (!(dev->flags & DM_FLAG_ACTIVATED))
  144. return 0;
  145. drv = dev->driver;
  146. assert(drv);
  147. ret = uclass_pre_remove_device(dev);
  148. if (ret)
  149. return ret;
  150. ret = device_chld_remove(dev, flags);
  151. if (ret)
  152. goto err;
  153. /*
  154. * Remove the device if called with the "normal" remove flag set,
  155. * or if the remove flag matches any of the drivers remove flags
  156. */
  157. if (drv->remove && flags_remove(flags, drv->flags)) {
  158. ret = drv->remove(dev);
  159. if (ret)
  160. goto err_remove;
  161. }
  162. if (dev->parent && dev->parent->driver->child_post_remove) {
  163. ret = dev->parent->driver->child_post_remove(dev);
  164. if (ret) {
  165. dm_warn("%s: Device '%s' failed child_post_remove()",
  166. __func__, dev->name);
  167. }
  168. }
  169. if (flags_remove(flags, drv->flags)) {
  170. device_free(dev);
  171. dev->seq = -1;
  172. dev->flags &= ~DM_FLAG_ACTIVATED;
  173. }
  174. return ret;
  175. err_remove:
  176. /* We can't put the children back */
  177. dm_warn("%s: Device '%s' failed to remove, but children are gone\n",
  178. __func__, dev->name);
  179. err:
  180. ret = uclass_post_probe_device(dev);
  181. if (ret) {
  182. dm_warn("%s: Device '%s' failed to post_probe on error path\n",
  183. __func__, dev->name);
  184. }
  185. return ret;
  186. }