device-remove.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Device manager
  4. *
  5. * Copyright (c) 2014 Google, Inc
  6. *
  7. * (C) Copyright 2012
  8. * Pavel Herrmann <morpheus.ibis@gmail.com>
  9. */
  10. #include <common.h>
  11. #include <errno.h>
  12. #include <log.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. #include <power-domain.h>
  20. int device_chld_unbind(struct udevice *dev, struct driver *drv)
  21. {
  22. struct udevice *pos, *n;
  23. int ret, saved_ret = 0;
  24. assert(dev);
  25. list_for_each_entry_safe(pos, n, &dev->child_head, sibling_node) {
  26. if (drv && (pos->driver != drv))
  27. continue;
  28. ret = device_unbind(pos);
  29. if (ret && !saved_ret) {
  30. log_warning("device '%s' failed to unbind\n",
  31. pos->name);
  32. saved_ret = ret;
  33. }
  34. }
  35. return log_ret(saved_ret);
  36. }
  37. int device_chld_remove(struct udevice *dev, struct driver *drv,
  38. uint flags)
  39. {
  40. struct udevice *pos, *n;
  41. int ret;
  42. assert(dev);
  43. list_for_each_entry_safe(pos, n, &dev->child_head, sibling_node) {
  44. if (drv && (pos->driver != drv))
  45. continue;
  46. ret = device_remove(pos, flags);
  47. if (ret)
  48. return ret;
  49. }
  50. return 0;
  51. }
  52. int device_unbind(struct udevice *dev)
  53. {
  54. const struct driver *drv;
  55. int ret;
  56. if (!dev)
  57. return log_msg_ret("dev", -EINVAL);
  58. if (dev->flags & DM_FLAG_ACTIVATED)
  59. return log_msg_ret("active", -EINVAL);
  60. if (!(dev->flags & DM_FLAG_BOUND))
  61. return log_msg_ret("not-bound", -EINVAL);
  62. drv = dev->driver;
  63. assert(drv);
  64. if (drv->unbind) {
  65. ret = drv->unbind(dev);
  66. if (ret)
  67. return log_msg_ret("unbind", ret);
  68. }
  69. ret = device_chld_unbind(dev, NULL);
  70. if (ret)
  71. return log_msg_ret("child unbind", ret);
  72. if (dev->flags & DM_FLAG_ALLOC_PDATA) {
  73. free(dev->platdata);
  74. dev->platdata = NULL;
  75. }
  76. if (dev->flags & DM_FLAG_ALLOC_UCLASS_PDATA) {
  77. free(dev->uclass_platdata);
  78. dev->uclass_platdata = NULL;
  79. }
  80. if (dev->flags & DM_FLAG_ALLOC_PARENT_PDATA) {
  81. free(dev->parent_platdata);
  82. dev->parent_platdata = NULL;
  83. }
  84. ret = uclass_unbind_device(dev);
  85. if (ret)
  86. return log_msg_ret("uc", ret);
  87. if (dev->parent)
  88. list_del(&dev->sibling_node);
  89. devres_release_all(dev);
  90. if (dev->flags & DM_FLAG_NAME_ALLOCED)
  91. free((char *)dev->name);
  92. free(dev);
  93. return 0;
  94. }
  95. /**
  96. * device_free() - Free memory buffers allocated by a device
  97. * @dev: Device that is to be started
  98. */
  99. void device_free(struct udevice *dev)
  100. {
  101. int size;
  102. if (dev->driver->priv_auto_alloc_size) {
  103. free(dev->priv);
  104. dev->priv = NULL;
  105. }
  106. size = dev->uclass->uc_drv->per_device_auto_alloc_size;
  107. if (size) {
  108. free(dev->uclass_priv);
  109. dev->uclass_priv = NULL;
  110. }
  111. if (dev->parent) {
  112. size = dev->parent->driver->per_child_auto_alloc_size;
  113. if (!size) {
  114. size = dev->parent->uclass->uc_drv->
  115. per_child_auto_alloc_size;
  116. }
  117. if (size) {
  118. free(dev->parent_priv);
  119. dev->parent_priv = NULL;
  120. }
  121. }
  122. dev->flags &= ~DM_FLAG_PLATDATA_VALID;
  123. devres_release_probe(dev);
  124. }
  125. static bool flags_remove(uint flags, uint drv_flags)
  126. {
  127. if ((flags & DM_REMOVE_NORMAL) ||
  128. (flags && (drv_flags & (DM_FLAG_ACTIVE_DMA | DM_FLAG_OS_PREPARE))))
  129. return true;
  130. return false;
  131. }
  132. int device_remove(struct udevice *dev, uint flags)
  133. {
  134. const struct driver *drv;
  135. int ret;
  136. if (!dev)
  137. return -EINVAL;
  138. if (!(dev->flags & DM_FLAG_ACTIVATED))
  139. return 0;
  140. drv = dev->driver;
  141. assert(drv);
  142. ret = uclass_pre_remove_device(dev);
  143. if (ret)
  144. return ret;
  145. ret = device_chld_remove(dev, NULL, flags);
  146. if (ret)
  147. goto err;
  148. /*
  149. * Remove the device if called with the "normal" remove flag set,
  150. * or if the remove flag matches any of the drivers remove flags
  151. */
  152. if (drv->remove && flags_remove(flags, drv->flags)) {
  153. ret = drv->remove(dev);
  154. if (ret)
  155. goto err_remove;
  156. }
  157. if (dev->parent && dev->parent->driver->child_post_remove) {
  158. ret = dev->parent->driver->child_post_remove(dev);
  159. if (ret) {
  160. dm_warn("%s: Device '%s' failed child_post_remove()",
  161. __func__, dev->name);
  162. }
  163. }
  164. if (!(flags & DM_REMOVE_NO_PD) &&
  165. !(drv->flags &
  166. (DM_FLAG_DEFAULT_PD_CTRL_OFF | DM_FLAG_REMOVE_WITH_PD_ON)) &&
  167. dev != gd->cur_serial_dev)
  168. dev_power_domain_off(dev);
  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. }