wlan_dsc_psoc.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. /*
  2. * Copyright (c) 2018 The Linux Foundation. All rights reserved.
  3. *
  4. * Permission to use, copy, modify, and/or distribute this software for
  5. * any purpose with or without fee is hereby granted, provided that the
  6. * above copyright notice and this permission notice appear in all
  7. * copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
  10. * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
  11. * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
  12. * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  13. * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  14. * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  15. * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  16. * PERFORMANCE OF THIS SOFTWARE.
  17. */
  18. #include "qdf_list.h"
  19. #include "qdf_mem.h"
  20. #include "qdf_status.h"
  21. #include "qdf_types.h"
  22. #include "__wlan_dsc.h"
  23. #include "wlan_dsc.h"
  24. static QDF_STATUS
  25. __dsc_psoc_create(struct dsc_driver *driver, struct dsc_psoc **out_psoc)
  26. {
  27. struct dsc_psoc *psoc;
  28. if (!dsc_assert(driver))
  29. return QDF_STATUS_E_INVAL;
  30. if (!dsc_assert(out_psoc))
  31. return QDF_STATUS_E_INVAL;
  32. *out_psoc = NULL;
  33. psoc = qdf_mem_malloc(sizeof(*psoc));
  34. if (!psoc)
  35. return QDF_STATUS_E_NOMEM;
  36. /* init */
  37. psoc->driver = driver;
  38. qdf_list_create(&psoc->vdevs, 0);
  39. __dsc_trans_init(&psoc->trans);
  40. __dsc_ops_init(&psoc->ops);
  41. /* attach */
  42. __dsc_lock();
  43. qdf_list_insert_back(&driver->psocs, &psoc->node);
  44. __dsc_unlock();
  45. *out_psoc = psoc;
  46. return QDF_STATUS_SUCCESS;
  47. }
  48. QDF_STATUS
  49. dsc_psoc_create(struct dsc_driver *driver, struct dsc_psoc **out_psoc)
  50. {
  51. QDF_STATUS status;
  52. dsc_enter();
  53. status = __dsc_psoc_create(driver, out_psoc);
  54. dsc_exit();
  55. return status;
  56. }
  57. static void __dsc_psoc_destroy(struct dsc_psoc **out_psoc)
  58. {
  59. struct dsc_psoc *psoc;
  60. if (!dsc_assert(out_psoc))
  61. return;
  62. psoc = *out_psoc;
  63. if (!dsc_assert(psoc))
  64. return;
  65. *out_psoc = NULL;
  66. /* assert no children */
  67. dsc_assert(qdf_list_empty(&psoc->vdevs));
  68. /* flush pending transitions */
  69. while (__dsc_trans_abort(&psoc->trans))
  70. ;
  71. /* detach */
  72. __dsc_lock();
  73. qdf_list_remove_node(&psoc->driver->psocs, &psoc->node);
  74. __dsc_unlock();
  75. /* de-init */
  76. __dsc_ops_deinit(&psoc->ops);
  77. __dsc_trans_deinit(&psoc->trans);
  78. qdf_list_destroy(&psoc->vdevs);
  79. psoc->driver = NULL;
  80. qdf_mem_free(psoc);
  81. }
  82. void dsc_psoc_destroy(struct dsc_psoc **out_psoc)
  83. {
  84. dsc_enter();
  85. __dsc_psoc_destroy(out_psoc);
  86. dsc_exit();
  87. }
  88. static bool __dsc_psoc_trans_active_down_tree(struct dsc_psoc *psoc)
  89. {
  90. struct dsc_vdev *vdev;
  91. dsc_for_each_psoc_vdev(psoc, vdev) {
  92. if (__dsc_trans_active(&vdev->trans))
  93. return true;
  94. }
  95. return false;
  96. }
  97. static bool __dsc_psoc_can_op(struct dsc_psoc *psoc)
  98. {
  99. return !__dsc_trans_active_or_queued(&psoc->driver->trans) &&
  100. !__dsc_trans_active_or_queued(&psoc->trans);
  101. }
  102. static bool __dsc_psoc_can_trans(struct dsc_psoc *psoc)
  103. {
  104. return !__dsc_trans_active_or_queued(&psoc->driver->trans) &&
  105. !__dsc_trans_active_or_queued(&psoc->trans) &&
  106. !__dsc_psoc_trans_active_down_tree(psoc);
  107. }
  108. static bool __dsc_psoc_can_trigger(struct dsc_psoc *psoc)
  109. {
  110. return !__dsc_trans_active_or_queued(&psoc->driver->trans) &&
  111. !__dsc_trans_active(&psoc->trans) &&
  112. !__dsc_psoc_trans_active_down_tree(psoc);
  113. }
  114. static QDF_STATUS
  115. __dsc_psoc_trans_start_nolock(struct dsc_psoc *psoc, const char *desc)
  116. {
  117. if (!__dsc_psoc_can_trans(psoc))
  118. return QDF_STATUS_E_AGAIN;
  119. psoc->trans.active_desc = desc;
  120. return QDF_STATUS_SUCCESS;
  121. }
  122. static QDF_STATUS
  123. __dsc_psoc_trans_start(struct dsc_psoc *psoc, const char *desc)
  124. {
  125. QDF_STATUS status;
  126. if (!dsc_assert(psoc))
  127. return QDF_STATUS_E_INVAL;
  128. if (!dsc_assert(desc))
  129. return QDF_STATUS_E_INVAL;
  130. __dsc_lock();
  131. status = __dsc_psoc_trans_start_nolock(psoc, desc);
  132. __dsc_unlock();
  133. return status;
  134. }
  135. QDF_STATUS dsc_psoc_trans_start(struct dsc_psoc *psoc, const char *desc)
  136. {
  137. QDF_STATUS status;
  138. dsc_enter_str(desc);
  139. status = __dsc_psoc_trans_start(psoc, desc);
  140. dsc_exit_status(status);
  141. return status;
  142. }
  143. static QDF_STATUS
  144. __dsc_psoc_trans_start_wait(struct dsc_psoc *psoc, const char *desc)
  145. {
  146. QDF_STATUS status;
  147. struct dsc_tran tran = { 0 };
  148. if (!dsc_assert(psoc))
  149. return QDF_STATUS_E_INVAL;
  150. if (!dsc_assert(desc))
  151. return QDF_STATUS_E_INVAL;
  152. __dsc_lock();
  153. status = __dsc_psoc_trans_start_nolock(psoc, desc);
  154. if (QDF_IS_STATUS_SUCCESS(status)) {
  155. __dsc_unlock();
  156. return QDF_STATUS_SUCCESS;
  157. }
  158. __dsc_trans_queue(&psoc->trans, &tran, desc);
  159. __dsc_unlock();
  160. return __dsc_tran_wait(&tran);
  161. }
  162. QDF_STATUS dsc_psoc_trans_start_wait(struct dsc_psoc *psoc, const char *desc)
  163. {
  164. QDF_STATUS status;
  165. dsc_enter_str(desc);
  166. status = __dsc_psoc_trans_start_wait(psoc, desc);
  167. dsc_exit_status(status);
  168. return status;
  169. }
  170. static void __dsc_psoc_trigger_trans(struct dsc_psoc *psoc)
  171. {
  172. struct dsc_vdev *vdev;
  173. if (__dsc_driver_trans_trigger_checked(psoc->driver))
  174. return;
  175. if (__dsc_trans_trigger(&psoc->trans))
  176. return;
  177. dsc_for_each_psoc_vdev(psoc, vdev)
  178. __dsc_trans_trigger(&vdev->trans);
  179. }
  180. static void __dsc_psoc_trans_stop(struct dsc_psoc *psoc)
  181. {
  182. if (!dsc_assert(psoc))
  183. return;
  184. dsc_assert(psoc->trans.active_desc);
  185. psoc->trans.active_desc = NULL;
  186. __dsc_psoc_trigger_trans(psoc);
  187. }
  188. void dsc_psoc_trans_stop(struct dsc_psoc *psoc)
  189. {
  190. dsc_enter();
  191. __dsc_lock();
  192. __dsc_psoc_trans_stop(psoc);
  193. __dsc_unlock();
  194. dsc_exit();
  195. }
  196. void dsc_psoc_trans_assert(struct dsc_psoc *psoc)
  197. {
  198. dsc_enter();
  199. __dsc_lock();
  200. dsc_assert(psoc->trans.active_desc);
  201. __dsc_unlock();
  202. dsc_exit();
  203. }
  204. bool __dsc_psoc_trans_trigger_checked(struct dsc_psoc *psoc)
  205. {
  206. if (qdf_list_empty(&psoc->trans.queue))
  207. return false;
  208. /* handled, but don't trigger; we need to wait for more children */
  209. if (!__dsc_psoc_can_trigger(psoc))
  210. return true;
  211. return __dsc_trans_trigger(&psoc->trans);
  212. }
  213. static QDF_STATUS __dsc_psoc_op_start(struct dsc_psoc *psoc, const char *func)
  214. {
  215. if (!dsc_assert(psoc))
  216. return QDF_STATUS_E_INVAL;
  217. if (!dsc_assert(func))
  218. return QDF_STATUS_E_INVAL;
  219. if (!__dsc_psoc_can_op(psoc))
  220. return QDF_STATUS_E_AGAIN;
  221. return __dsc_ops_insert(&psoc->ops, func);
  222. }
  223. QDF_STATUS _dsc_psoc_op_start(struct dsc_psoc *psoc, const char *func)
  224. {
  225. QDF_STATUS status;
  226. dsc_enter_str(func);
  227. __dsc_lock();
  228. status = __dsc_psoc_op_start(psoc, func);
  229. __dsc_unlock();
  230. dsc_exit_status(status);
  231. return status;
  232. }
  233. static void __dsc_psoc_op_stop(struct dsc_psoc *psoc, const char *func)
  234. {
  235. if (!dsc_assert(psoc))
  236. return;
  237. if (!dsc_assert(func))
  238. return;
  239. if (__dsc_ops_remove(&psoc->ops, func))
  240. qdf_event_set(&psoc->ops.event);
  241. }
  242. void _dsc_psoc_op_stop(struct dsc_psoc *psoc, const char *func)
  243. {
  244. dsc_enter_str(func);
  245. __dsc_lock();
  246. __dsc_psoc_op_stop(psoc, func);
  247. __dsc_unlock();
  248. dsc_exit();
  249. }
  250. static void __dsc_psoc_wait_for_ops(struct dsc_psoc *psoc)
  251. {
  252. struct dsc_vdev *vdev;
  253. bool wait;
  254. if (!dsc_assert(psoc))
  255. return;
  256. __dsc_lock();
  257. /* flushing without preventing new ops is almost certainly a bug */
  258. dsc_assert(!__dsc_psoc_can_op(psoc));
  259. wait = psoc->ops.count > 0;
  260. if (wait)
  261. qdf_event_reset(&psoc->ops.event);
  262. __dsc_unlock();
  263. if (wait)
  264. qdf_wait_single_event(&psoc->ops.event, 0);
  265. /* wait for down-tree ops to complete as well */
  266. dsc_for_each_psoc_vdev(psoc, vdev)
  267. dsc_vdev_wait_for_ops(vdev);
  268. }
  269. void dsc_psoc_wait_for_ops(struct dsc_psoc *psoc)
  270. {
  271. dsc_enter();
  272. __dsc_psoc_wait_for_ops(psoc);
  273. dsc_exit();
  274. }