apr_tal_rpmsg.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved.
  4. */
  5. #include <linux/module.h>
  6. #include <linux/spinlock.h>
  7. #include <linux/mutex.h>
  8. #include <linux/wait.h>
  9. #include <linux/delay.h>
  10. #include <linux/rpmsg.h>
  11. #include <ipc/apr_tal.h>
  12. enum apr_channel_state {
  13. APR_CH_DISCONNECTED,
  14. APR_CH_CONNECTED,
  15. };
  16. #define APR_MAXIMUM_NUM_OF_RETRIES 2
  17. static struct apr_svc_ch_dev
  18. apr_svc_ch[APR_DL_MAX][APR_DEST_MAX][APR_CLIENT_MAX];
  19. /**
  20. * apr_tal_write() - Write a message across to the remote processor
  21. * @apr_ch: apr channel handle
  22. * @data: buffer that needs to be transferred over the channel
  23. * @pkt_priv: private data of the packet
  24. * @len: length of the buffer
  25. *
  26. * Returns len of buffer successfully transferred on success
  27. * and an appropriate error value on failure.
  28. */
  29. int apr_tal_write(struct apr_svc_ch_dev *apr_ch, void *data,
  30. struct apr_pkt_priv *pkt_priv, int len)
  31. {
  32. int rc = 0, retries = 0;
  33. unsigned long flags;
  34. struct rpmsg_device *rpdev = NULL;
  35. if (!apr_ch || len > APR_MAX_BUF ||
  36. apr_ch->channel_state != APR_CH_CONNECTED)
  37. return -EINVAL;
  38. spin_lock_irqsave(&apr_ch->w_lock, flags);
  39. rpdev = apr_ch->handle;
  40. if (!rpdev) {
  41. spin_unlock_irqrestore(&apr_ch->w_lock, flags);
  42. return -EINVAL;
  43. }
  44. do {
  45. if (rc == -EAGAIN)
  46. udelay(50);
  47. rc = rpmsg_trysend(rpdev->ept, data, len);
  48. } while (rc == -EAGAIN && retries++ < APR_MAXIMUM_NUM_OF_RETRIES);
  49. spin_unlock_irqrestore(&apr_ch->w_lock, flags);
  50. if (rc)
  51. pr_err("%s: Unable to send the packet, rc:%d\n", __func__, rc);
  52. else
  53. rc = len;
  54. return rc;
  55. }
  56. EXPORT_SYMBOL(apr_tal_write);
  57. /**
  58. * apr_tal_rx_intents_config() - Configure glink intents for remote processor
  59. * @apr_ch: apr channel handle
  60. * @num_of_intents: number of intents
  61. * @size: size of the intents
  62. *
  63. * This api is not supported with RPMSG. Returns 0 to indicate success
  64. */
  65. int apr_tal_rx_intents_config(struct apr_svc_ch_dev *apr_ch,
  66. int num_of_intents, uint32_t size)
  67. {
  68. pr_debug("%s: NO-OP\n", __func__);
  69. return 0;
  70. }
  71. EXPORT_SYMBOL(apr_tal_rx_intents_config);
  72. /**
  73. * apr_tal_start_rx_rt() - Set RT thread priority for APR RX transfer
  74. * @apr_ch: apr channel handle
  75. *
  76. * This api is not supported with RPMSG as message transfer occurs
  77. * in client's context. Returns 0 to indicate success.
  78. */
  79. int apr_tal_start_rx_rt(struct apr_svc_ch_dev *apr_ch)
  80. {
  81. pr_debug("%s: NO-OP\n", __func__);
  82. return 0;
  83. }
  84. EXPORT_SYMBOL(apr_tal_start_rx_rt);
  85. /**
  86. * apr_tal_end_rx_rt() - Remove RT thread priority for APR RX transfer
  87. * @apr_ch: apr channel handle
  88. *
  89. * This api is not supported with RPMSG. Returns 0 to indicate success
  90. */
  91. int apr_tal_end_rx_rt(struct apr_svc_ch_dev *apr_ch)
  92. {
  93. pr_debug("%s: NO-OP\n", __func__);
  94. return 0;
  95. }
  96. EXPORT_SYMBOL(apr_tal_end_rx_rt);
  97. /**
  98. * apr_tal_open() - Open a transport channel for data transfer
  99. * on remote processor.
  100. * @clnt: apr client, audio or voice
  101. * @dest: destination remote processor for which apr channel is requested for.
  102. * @dl: type of data link
  103. * @func: callback function to handle data transfer from remote processor
  104. * @priv: private data of the client
  105. *
  106. * Returns apr_svc_ch_dev handle on success and NULL on failure.
  107. */
  108. struct apr_svc_ch_dev *apr_tal_open(uint32_t clnt, uint32_t dest, uint32_t dl,
  109. apr_svc_cb_fn func, void *priv)
  110. {
  111. int rc = 0;
  112. struct apr_svc_ch_dev *apr_ch = NULL;
  113. if ((clnt != APR_CLIENT_AUDIO) || (dest != APR_DEST_QDSP6) ||
  114. (dl != APR_DL_SMD)) {
  115. pr_err("%s: Invalid params, clnt:%d, dest:%d, dl:%d\n",
  116. __func__, clnt, dest, dl);
  117. return NULL;
  118. }
  119. apr_ch = &apr_svc_ch[APR_DL_SMD][APR_DEST_QDSP6][APR_CLIENT_AUDIO];
  120. mutex_lock(&apr_ch->m_lock);
  121. if (!apr_ch->handle) {
  122. rc = wait_event_timeout(apr_ch->wait,
  123. (apr_ch->channel_state == APR_CH_CONNECTED), 5 * HZ);
  124. if (rc == 0) {
  125. pr_err("%s: TIMEOUT for APR_CH_CONNECTED event\n",
  126. __func__);
  127. rc = -ETIMEDOUT;
  128. goto unlock;
  129. }
  130. }
  131. pr_debug("%s: Channel connected, returning handle :%pK\n",
  132. __func__, apr_ch->handle);
  133. apr_ch->func = func;
  134. apr_ch->priv = priv;
  135. unlock:
  136. mutex_unlock(&apr_ch->m_lock);
  137. return rc ? NULL : apr_ch;
  138. }
  139. EXPORT_SYMBOL(apr_tal_open);
  140. /**
  141. * apr_tal_close() - Close transport channel on remote processor.
  142. * @apr_ch: apr channel handle
  143. *
  144. * Returns 0 on success and an appropriate error value on failure.
  145. */
  146. int apr_tal_close(struct apr_svc_ch_dev *apr_ch)
  147. {
  148. int rc = 0;
  149. if (!apr_ch || !apr_ch->handle) {
  150. rc = -EINVAL;
  151. goto exit;
  152. }
  153. mutex_lock(&apr_ch->m_lock);
  154. apr_ch->func = NULL;
  155. apr_ch->priv = NULL;
  156. mutex_unlock(&apr_ch->m_lock);
  157. exit:
  158. return rc;
  159. }
  160. EXPORT_SYMBOL(apr_tal_close);
  161. static int apr_tal_rpmsg_callback(struct rpmsg_device *rpdev,
  162. void *data, int len, void *priv, u32 addr)
  163. {
  164. struct apr_svc_ch_dev *apr_ch = dev_get_drvdata(&rpdev->dev);
  165. unsigned long flags;
  166. if (!apr_ch || !data) {
  167. pr_err("%s: Invalid apr_ch or ptr\n", __func__);
  168. return -EINVAL;
  169. }
  170. dev_dbg(&rpdev->dev, "%s: Rx packet received, len:%d\n",
  171. __func__, len);
  172. spin_lock_irqsave(&apr_ch->r_lock, flags);
  173. if (apr_ch->func)
  174. apr_ch->func((void *)data, len, apr_ch->priv);
  175. spin_unlock_irqrestore(&apr_ch->r_lock, flags);
  176. return 0;
  177. }
  178. static int apr_tal_rpmsg_probe(struct rpmsg_device *rpdev)
  179. {
  180. struct apr_svc_ch_dev *apr_ch = NULL;
  181. if (!strcmp(rpdev->id.name, "apr_audio_svc")) {
  182. dev_info(&rpdev->dev, "%s: Channel[%s] state[Up]\n",
  183. __func__, rpdev->id.name);
  184. apr_ch =
  185. &apr_svc_ch[APR_DL_SMD][APR_DEST_QDSP6][APR_CLIENT_AUDIO];
  186. apr_ch->handle = rpdev;
  187. apr_ch->channel_state = APR_CH_CONNECTED;
  188. dev_set_drvdata(&rpdev->dev, apr_ch);
  189. wake_up(&apr_ch->wait);
  190. } else {
  191. dev_err(&rpdev->dev, "%s, Invalid Channel [%s]\n",
  192. __func__, rpdev->id.name);
  193. return -EINVAL;
  194. }
  195. return 0;
  196. }
  197. static void apr_tal_rpmsg_remove(struct rpmsg_device *rpdev)
  198. {
  199. struct apr_svc_ch_dev *apr_ch = dev_get_drvdata(&rpdev->dev);
  200. if (!apr_ch) {
  201. dev_err(&rpdev->dev, "%s: Invalid apr_ch\n", __func__);
  202. return;
  203. }
  204. dev_info(&rpdev->dev, "%s: Channel[%s] state[Down]\n",
  205. __func__, rpdev->id.name);
  206. apr_ch->handle = NULL;
  207. apr_ch->channel_state = APR_CH_DISCONNECTED;
  208. dev_set_drvdata(&rpdev->dev, NULL);
  209. }
  210. static const struct rpmsg_device_id apr_tal_rpmsg_match[] = {
  211. { "apr_audio_svc" },
  212. {}
  213. };
  214. static struct rpmsg_driver apr_tal_rpmsg_driver = {
  215. .probe = apr_tal_rpmsg_probe,
  216. .remove = apr_tal_rpmsg_remove,
  217. .callback = apr_tal_rpmsg_callback,
  218. .id_table = apr_tal_rpmsg_match,
  219. .drv = {
  220. .name = "apr_tal_rpmsg",
  221. },
  222. };
  223. /**
  224. * apr_tal_int() - Registers rpmsg driver with rpmsg framework.
  225. *
  226. * Returns 0 on success and an appropriate error value on failure.
  227. */
  228. int apr_tal_init(void)
  229. {
  230. int i, j, k;
  231. int ret;
  232. memset(apr_svc_ch, 0, sizeof(struct apr_svc_ch_dev));
  233. for (i = 0; i < APR_DL_MAX; i++) {
  234. for (j = 0; j < APR_DEST_MAX; j++) {
  235. for (k = 0; k < APR_CLIENT_MAX; k++) {
  236. init_waitqueue_head(&apr_svc_ch[i][j][k].wait);
  237. spin_lock_init(&apr_svc_ch[i][j][k].w_lock);
  238. spin_lock_init(&apr_svc_ch[i][j][k].r_lock);
  239. mutex_init(&apr_svc_ch[i][j][k].m_lock);
  240. }
  241. }
  242. }
  243. ret = register_rpmsg_driver(&apr_tal_rpmsg_driver);
  244. return ret;
  245. }
  246. EXPORT_SYMBOL(apr_tal_init);
  247. /**
  248. * apr_tal_exit() - De-register rpmsg driver with rpmsg framework.
  249. */
  250. void apr_tal_exit(void)
  251. {
  252. unregister_rpmsg_driver(&apr_tal_rpmsg_driver);
  253. }
  254. EXPORT_SYMBOL(apr_tal_exit);