builder_pattern.h 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * COPYRIGHT(C) 2020-2021 Samsung Electronics Co., Ltd. All Right Reserved.
  4. */
  5. #ifndef __BUILDER_PATTERN_H__
  6. #define __BUILDER_PATTERN_H__
  7. #include <linux/device.h>
  8. #include <linux/kernel.h>
  9. #include <linux/kthread.h>
  10. #include <linux/of.h>
  11. struct director_threaded;
  12. /* An interface 'Builder' struct
  13. * TODO: This struct should be embedded if the drvdata use
  14. * this 'Builder Pattern'.
  15. */
  16. struct builder {
  17. struct device *dev;
  18. struct director_threaded *drct;
  19. };
  20. #define DT_BUILDER(__parse_dt) \
  21. { .parse_dt = __parse_dt, }
  22. /* The prototype of 'Concrete Builde' parsing a device tree */
  23. typedef int (*parse_dt_t)(struct builder *bd, struct device_node *np);
  24. struct dt_builder {
  25. parse_dt_t parse_dt;
  26. };
  27. #define DEVICE_BUILDER(__construct_dev, __destruct_dev) \
  28. { .construct_dev = __construct_dev, .destruct_dev = __destruct_dev, }
  29. /* The prototype of 'Concrete Builde' constructing a device */
  30. typedef int (*construct_dev_t)(struct builder *bd);
  31. /* The prototype of 'Concrete Builde' destructing a device */
  32. typedef void (*destruct_dev_t)(struct builder *bd);
  33. struct dev_builder {
  34. construct_dev_t construct_dev;
  35. destruct_dev_t destruct_dev;
  36. };
  37. #ifdef _DEBUG_BUILDER_PATTERN
  38. static inline int __bp_call_parse_dt(parse_dt_t parse_dt,
  39. struct builder *bd, struct device_node *np)
  40. {
  41. ktime_t calltime, rettime;
  42. int err;
  43. calltime = ktime_get();
  44. err = parse_dt(bd, np);
  45. rettime = ktime_get();
  46. dev_info(bd->dev, "%ps returned %d after %llu\n",
  47. parse_dt, err,
  48. (unsigned long long)ktime_sub(rettime, calltime));
  49. return err;
  50. }
  51. static inline int __bp_call_construct_dev(construct_dev_t construct_dev,
  52. struct builder *bd)
  53. {
  54. ktime_t calltime, rettime;
  55. int err;
  56. calltime = ktime_get();
  57. err = construct_dev(bd);
  58. rettime = ktime_get();
  59. dev_info(bd->dev, "%ps returned %d after %llu\n",
  60. construct_dev , err,
  61. (unsigned long long)ktime_sub(rettime, calltime));
  62. return err;
  63. }
  64. static inline void __bp_call_destruct_dev(destruct_dev_t destruct_dev,
  65. struct builder *bd)
  66. {
  67. ktime_t calltime, rettime;
  68. calltime = ktime_get();
  69. destruct_dev(bd);
  70. rettime = ktime_get();
  71. dev_info(bd->dev, "%ps returned after %llu\n",
  72. destruct_dev,
  73. (unsigned long long)ktime_sub(rettime, calltime));
  74. }
  75. #else
  76. static inline int __bp_call_parse_dt(parse_dt_t parse_dt,
  77. struct builder *bd, struct device_node *np)
  78. {
  79. return parse_dt(bd, np);
  80. }
  81. static inline int __bp_call_construct_dev(construct_dev_t construct_dev,
  82. struct builder *bd)
  83. {
  84. return construct_dev(bd);
  85. }
  86. static inline void __bp_call_destruct_dev(destruct_dev_t destruct_dev,
  87. struct builder *bd)
  88. {
  89. destruct_dev(bd);
  90. }
  91. #endif
  92. static inline int __bp_call_concrete_parse_dt(struct builder *bd,
  93. const struct dt_builder *builder, size_t i)
  94. {
  95. struct device_node *np = dev_of_node(bd->dev);
  96. int err;
  97. parse_dt_t parse_dt = builder[i].parse_dt;
  98. err = __bp_call_parse_dt(parse_dt, bd, np);
  99. if (err)
  100. dev_err(bd->dev, "failed to parse a device tree - [%zu] %ps (%d)\n",
  101. i, parse_dt, err);
  102. return err;
  103. }
  104. static inline int __bp_call_concrete_construct_dev(struct builder *bd,
  105. const struct dev_builder *builder, size_t i)
  106. {
  107. int err;
  108. construct_dev_t construct_dev = builder[i].construct_dev;
  109. if (!construct_dev)
  110. return 0;
  111. err = __bp_call_construct_dev(construct_dev, bd);
  112. if (err)
  113. dev_err(bd->dev, "failed to construct_dev a device - [%zu] %ps (%d)\n",
  114. i, construct_dev, err);
  115. return err;
  116. }
  117. static inline void __bp_call_concrete_destruct_dev(struct builder *bd,
  118. const struct dev_builder *builder, size_t i)
  119. {
  120. destruct_dev_t destruct_dev = builder[i].destruct_dev;
  121. if (!destruct_dev)
  122. return;
  123. __bp_call_destruct_dev(destruct_dev, bd);
  124. }
  125. /* A common 'Director' parsing a device tree
  126. * @return - 0 on success. 'errno' of last failed on failure.
  127. */
  128. static inline int sec_director_parse_dt(struct builder *bd,
  129. const struct dt_builder *builder, size_t n)
  130. {
  131. int err;
  132. size_t i;
  133. for (i = 0; i < n; i++) {
  134. err = __bp_call_concrete_parse_dt(bd, builder, i);
  135. if (err)
  136. return err;
  137. }
  138. return 0;
  139. }
  140. /* A common 'Director' constructing a device
  141. * @last_failed - The number of called builders on success.
  142. * The "NEGATIVE" index of last failed on failure.
  143. * @return - 0 on success.
  144. * return value of the last concrete builder on failure.
  145. */
  146. static inline int sec_director_construct_dev(struct builder *bd,
  147. const struct dev_builder *builder, ssize_t n,
  148. ssize_t *last_failed)
  149. {
  150. int err;
  151. ssize_t i;
  152. for (i = 0; i < n; i++) {
  153. err = __bp_call_concrete_construct_dev(bd, builder, i);
  154. if (err) {
  155. *last_failed = -i;
  156. return err;
  157. }
  158. }
  159. *last_failed = n;
  160. return 0;
  161. }
  162. /* A common 'Director' destructing a device */
  163. static inline void sec_director_destruct_dev(struct builder *bd,
  164. const struct dev_builder *builder, ssize_t n,
  165. ssize_t last_failed)
  166. {
  167. ssize_t i;
  168. BUG_ON((last_failed > n) || (last_failed < 0));
  169. for (i = last_failed - 1; i >= 0; i--)
  170. __bp_call_concrete_destruct_dev(bd, builder, i);
  171. }
  172. /* A wrapper function for probe call-backs */
  173. static inline int sec_director_probe_dev(struct builder *bd,
  174. const struct dev_builder *builder, ssize_t n)
  175. {
  176. int err;
  177. ssize_t last_failed;
  178. err = sec_director_construct_dev(bd, builder, n, &last_failed);
  179. if (last_failed <= 0)
  180. goto err_dev_director;
  181. return 0;
  182. err_dev_director:
  183. sec_director_destruct_dev(bd, builder, n, -last_failed);
  184. return err;
  185. }
  186. struct director_threaded {
  187. struct builder *bd;
  188. const struct dev_builder *builder;
  189. ssize_t n;
  190. int *construct_result;
  191. };
  192. /* A common 'Director' constructing a device - threaded */
  193. static int sec_director_construct_dev_threaded(void *__drct)
  194. {
  195. struct director_threaded *drct = __drct;
  196. struct builder *bd = drct->bd;
  197. const struct dev_builder *builder = drct->builder;
  198. ssize_t n = drct->n;
  199. int *construct_result = drct->construct_result;
  200. ssize_t i;
  201. for (i = 0; i < n; i++)
  202. construct_result[i] =
  203. __bp_call_concrete_construct_dev(bd, builder, i);
  204. return 0;
  205. }
  206. /* A common 'Director' destructing a device */
  207. static inline void sec_director_destruct_dev_threaded(
  208. struct director_threaded *drct)
  209. {
  210. struct builder *bd = drct->bd;
  211. const struct dev_builder *builder = drct->builder;
  212. ssize_t n = drct->n;
  213. int *construct_result = drct->construct_result;
  214. ssize_t i;
  215. for (i = n - 1; i >= 0; i--) {
  216. if (!construct_result[i])
  217. __bp_call_concrete_destruct_dev(bd, builder, i);
  218. }
  219. }
  220. /* A wrapper function for probe call-backs - threaded */
  221. static inline int sec_director_probe_dev_threaded(struct builder *bd,
  222. const struct dev_builder *builder, ssize_t n, const char *name)
  223. {
  224. struct device *dev = bd->dev;
  225. struct director_threaded *drct;
  226. int *construct_result;
  227. struct task_struct *thread;
  228. drct = devm_kzalloc(dev, sizeof(*drct), GFP_KERNEL);
  229. if (!drct)
  230. return -ENOMEM;
  231. construct_result = devm_kcalloc(dev, n, sizeof(*construct_result),
  232. GFP_KERNEL);
  233. if (!construct_result)
  234. return -ENOMEM;
  235. drct->bd = bd;
  236. drct->builder = builder;
  237. drct->n = n;
  238. drct->construct_result = construct_result;
  239. thread = kthread_run(sec_director_construct_dev_threaded,
  240. drct, "drct-%s", name);
  241. if (IS_ERR_OR_NULL(thread)) {
  242. dev_err(dev, "failed to created drct thread - (%ld)!\n",
  243. PTR_ERR(thread));
  244. return -ENOMEM;
  245. }
  246. bd->drct = drct;
  247. return 0;
  248. }
  249. #endif /* __BUILDER_PATTERN_H__ */