wlan_dsc_vdev.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  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. #define __dsc_driver_lock(vdev) __dsc_lock((vdev)->psoc->driver)
  25. #define __dsc_driver_unlock(vdev) __dsc_unlock((vdev)->psoc->driver)
  26. static QDF_STATUS
  27. __dsc_vdev_create(struct dsc_psoc *psoc, struct dsc_vdev **out_vdev)
  28. {
  29. struct dsc_vdev *vdev;
  30. if (!dsc_assert(psoc))
  31. return QDF_STATUS_E_INVAL;
  32. if (!dsc_assert(out_vdev))
  33. return QDF_STATUS_E_INVAL;
  34. *out_vdev = NULL;
  35. vdev = qdf_mem_malloc(sizeof(*vdev));
  36. if (!vdev)
  37. return QDF_STATUS_E_NOMEM;
  38. /* init */
  39. vdev->psoc = psoc;
  40. __dsc_trans_init(&vdev->trans);
  41. __dsc_ops_init(&vdev->ops);
  42. /* attach */
  43. __dsc_driver_lock(vdev);
  44. qdf_list_insert_back(&psoc->vdevs, &vdev->node);
  45. __dsc_driver_unlock(vdev);
  46. *out_vdev = vdev;
  47. return QDF_STATUS_SUCCESS;
  48. }
  49. QDF_STATUS dsc_vdev_create(struct dsc_psoc *psoc, struct dsc_vdev **out_vdev)
  50. {
  51. QDF_STATUS status;
  52. dsc_enter();
  53. status = __dsc_vdev_create(psoc, out_vdev);
  54. dsc_exit();
  55. return status;
  56. }
  57. static void __dsc_vdev_destroy(struct dsc_vdev **out_vdev)
  58. {
  59. struct dsc_vdev *vdev;
  60. if (!dsc_assert(out_vdev))
  61. return;
  62. vdev = *out_vdev;
  63. if (!dsc_assert(vdev))
  64. return;
  65. *out_vdev = NULL;
  66. /* flush pending transitions */
  67. while (__dsc_trans_abort(&vdev->trans))
  68. ;
  69. /* detach */
  70. __dsc_driver_lock(vdev);
  71. qdf_list_remove_node(&vdev->psoc->vdevs, &vdev->node);
  72. __dsc_driver_unlock(vdev);
  73. /* de-init */
  74. __dsc_ops_deinit(&vdev->ops);
  75. __dsc_trans_deinit(&vdev->trans);
  76. vdev->psoc = NULL;
  77. qdf_mem_free(vdev);
  78. }
  79. void dsc_vdev_destroy(struct dsc_vdev **out_vdev)
  80. {
  81. dsc_enter();
  82. __dsc_vdev_destroy(out_vdev);
  83. dsc_exit();
  84. }
  85. static bool __dsc_vdev_can_op(struct dsc_vdev *vdev)
  86. {
  87. return !__dsc_trans_active_or_queued(&vdev->psoc->driver->trans) &&
  88. !__dsc_trans_active_or_queued(&vdev->psoc->trans) &&
  89. !__dsc_trans_active_or_queued(&vdev->trans);
  90. }
  91. static bool __dsc_vdev_can_trans(struct dsc_vdev *vdev)
  92. {
  93. return __dsc_vdev_can_op(vdev);
  94. }
  95. static QDF_STATUS
  96. __dsc_vdev_trans_start_nolock(struct dsc_vdev *vdev, const char *desc)
  97. {
  98. if (!__dsc_vdev_can_trans(vdev))
  99. return QDF_STATUS_E_AGAIN;
  100. return __dsc_trans_start(&vdev->trans, desc);
  101. }
  102. static QDF_STATUS
  103. __dsc_vdev_trans_start(struct dsc_vdev *vdev, const char *desc)
  104. {
  105. QDF_STATUS status;
  106. if (!dsc_assert(vdev))
  107. return QDF_STATUS_E_INVAL;
  108. if (!dsc_assert(desc))
  109. return QDF_STATUS_E_INVAL;
  110. __dsc_driver_lock(vdev);
  111. status = __dsc_vdev_trans_start_nolock(vdev, desc);
  112. __dsc_driver_unlock(vdev);
  113. return status;
  114. }
  115. QDF_STATUS dsc_vdev_trans_start(struct dsc_vdev *vdev, const char *desc)
  116. {
  117. QDF_STATUS status;
  118. dsc_enter_str(desc);
  119. status = __dsc_vdev_trans_start(vdev, desc);
  120. dsc_exit_status(status);
  121. return status;
  122. }
  123. static QDF_STATUS
  124. __dsc_vdev_trans_start_wait(struct dsc_vdev *vdev, const char *desc)
  125. {
  126. QDF_STATUS status;
  127. struct dsc_tran tran = { 0 };
  128. if (!dsc_assert(vdev))
  129. return QDF_STATUS_E_INVAL;
  130. if (!dsc_assert(desc))
  131. return QDF_STATUS_E_INVAL;
  132. __dsc_driver_lock(vdev);
  133. /* try to start without waiting */
  134. status = __dsc_vdev_trans_start_nolock(vdev, desc);
  135. if (QDF_IS_STATUS_SUCCESS(status))
  136. goto unlock;
  137. status = __dsc_trans_queue(&vdev->trans, &tran, desc);
  138. if (QDF_IS_STATUS_ERROR(status))
  139. goto unlock;
  140. __dsc_driver_unlock(vdev);
  141. return __dsc_tran_wait(&tran);
  142. unlock:
  143. __dsc_driver_unlock(vdev);
  144. return status;
  145. }
  146. QDF_STATUS dsc_vdev_trans_start_wait(struct dsc_vdev *vdev, const char *desc)
  147. {
  148. QDF_STATUS status;
  149. dsc_enter_str(desc);
  150. status = __dsc_vdev_trans_start_wait(vdev, desc);
  151. dsc_exit_status(status);
  152. return status;
  153. }
  154. static void __dsc_vdev_trigger_trans(struct dsc_vdev *vdev)
  155. {
  156. if (__dsc_driver_trans_trigger_checked(vdev->psoc->driver))
  157. return;
  158. if (__dsc_psoc_trans_trigger_checked(vdev->psoc))
  159. return;
  160. __dsc_trans_trigger(&vdev->trans);
  161. }
  162. static void __dsc_vdev_trans_stop(struct dsc_vdev *vdev)
  163. {
  164. if (!dsc_assert(vdev))
  165. return;
  166. __dsc_driver_lock(vdev);
  167. __dsc_trans_stop(&vdev->trans);
  168. __dsc_vdev_trigger_trans(vdev);
  169. __dsc_driver_unlock(vdev);
  170. }
  171. void dsc_vdev_trans_stop(struct dsc_vdev *vdev)
  172. {
  173. dsc_enter();
  174. __dsc_vdev_trans_stop(vdev);
  175. dsc_exit();
  176. }
  177. static void __dsc_vdev_assert_trans_protected(struct dsc_vdev *vdev)
  178. {
  179. if (!dsc_assert(vdev))
  180. return;
  181. __dsc_driver_lock(vdev);
  182. dsc_assert(__dsc_trans_active(&vdev->trans) ||
  183. __dsc_trans_active(&vdev->psoc->trans) ||
  184. __dsc_trans_active(&vdev->psoc->driver->trans));
  185. __dsc_driver_unlock(vdev);
  186. }
  187. void dsc_vdev_assert_trans_protected(struct dsc_vdev *vdev)
  188. {
  189. dsc_enter();
  190. __dsc_vdev_assert_trans_protected(vdev);
  191. dsc_exit();
  192. }
  193. static QDF_STATUS __dsc_vdev_op_start(struct dsc_vdev *vdev, const char *func)
  194. {
  195. QDF_STATUS status;
  196. if (!dsc_assert(vdev))
  197. return QDF_STATUS_E_INVAL;
  198. if (!dsc_assert(func))
  199. return QDF_STATUS_E_INVAL;
  200. __dsc_driver_lock(vdev);
  201. if (!__dsc_vdev_can_op(vdev)) {
  202. status = QDF_STATUS_E_AGAIN;
  203. goto unlock;
  204. }
  205. status = __dsc_ops_insert(&vdev->ops, func);
  206. unlock:
  207. __dsc_driver_unlock(vdev);
  208. return status;
  209. }
  210. QDF_STATUS _dsc_vdev_op_start(struct dsc_vdev *vdev, const char *func)
  211. {
  212. QDF_STATUS status;
  213. dsc_enter_str(func);
  214. status = __dsc_vdev_op_start(vdev, func);
  215. dsc_exit_status(status);
  216. return status;
  217. }
  218. static void __dsc_vdev_op_stop(struct dsc_vdev *vdev, const char *func)
  219. {
  220. if (!dsc_assert(vdev))
  221. return;
  222. if (!dsc_assert(func))
  223. return;
  224. __dsc_driver_lock(vdev);
  225. if (__dsc_ops_remove(&vdev->ops, func))
  226. qdf_event_set(&vdev->ops.event);
  227. __dsc_driver_unlock(vdev);
  228. }
  229. void _dsc_vdev_op_stop(struct dsc_vdev *vdev, const char *func)
  230. {
  231. dsc_enter_str(func);
  232. __dsc_vdev_op_stop(vdev, func);
  233. dsc_exit();
  234. }
  235. static void __dsc_vdev_wait_for_ops(struct dsc_vdev *vdev)
  236. {
  237. bool wait;
  238. if (!dsc_assert(vdev))
  239. return;
  240. __dsc_driver_lock(vdev);
  241. /* flushing without preventing new ops is almost certainly a bug */
  242. dsc_assert(!__dsc_vdev_can_op(vdev));
  243. wait = vdev->ops.count > 0;
  244. if (wait)
  245. qdf_event_reset(&vdev->ops.event);
  246. __dsc_driver_unlock(vdev);
  247. if (wait)
  248. qdf_wait_single_event(&vdev->ops.event, 0);
  249. }
  250. void dsc_vdev_wait_for_ops(struct dsc_vdev *vdev)
  251. {
  252. dsc_enter();
  253. __dsc_vdev_wait_for_ops(vdev);
  254. dsc_exit();
  255. }