blob: 6683348686aae816a3bdcbb05d42120da8f1c23d [file] [log] [blame]
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301/*
2 * Copyright (c) 2016-2017 The Linux Foundation. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14#include <linux/kernel.h>
15#include <linux/module.h>
16#include <linux/types.h>
17#include <linux/uaccess.h>
18#include <linux/spinlock.h>
19#include <linux/mutex.h>
20#include <linux/sched.h>
21#include <linux/wait.h>
22#include <linux/errno.h>
23#include <linux/fs.h>
24#include <linux/slab.h>
25#include <linux/debugfs.h>
26#include <linux/platform_device.h>
27#include <linux/delay.h>
28#include <linux/clk.h>
29#include <soc/qcom/glink.h>
Laxminath Kasam605b42f2017-08-01 22:02:15 +053030#include <ipc/apr_tal.h>
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053031
32#define APR_MAXIMUM_NUM_OF_RETRIES 2
33
34struct apr_tx_buf {
35 struct apr_pkt_priv pkt_priv;
36 char buf[APR_MAX_BUF];
37};
38
39struct link_state {
40 uint32_t dest;
41 void *handle;
42 enum glink_link_state link_state;
43 wait_queue_head_t wait;
44};
45
46static struct link_state link_state[APR_DEST_MAX];
47
48static char *svc_names[APR_DEST_MAX][APR_CLIENT_MAX] = {
49 {
50 "apr_audio_svc",
51 "apr_voice_svc",
52 },
53 {
54 "apr_audio_svc",
55 "apr_voice_svc",
56 },
57};
58
59static struct apr_svc_ch_dev
60 apr_svc_ch[APR_DL_MAX][APR_DEST_MAX][APR_CLIENT_MAX];
61
62static struct apr_tx_buf *apr_alloc_buf(int len)
63{
64
65 if (len > APR_MAX_BUF) {
66 pr_err("%s: buf too large [%d]\n", __func__, len);
67 return ERR_PTR(-EINVAL);
68 }
69
70 return kzalloc(sizeof(struct apr_tx_buf), GFP_ATOMIC);
71}
72
73static void apr_free_buf(const void *ptr)
74{
75
76 struct apr_pkt_priv *apr_pkt_priv = (struct apr_pkt_priv *)ptr;
77 struct apr_tx_buf *tx_buf;
78
79 if (!apr_pkt_priv) {
80 pr_err("%s: Invalid apr_pkt_priv\n", __func__);
81 return;
82 }
83
84 if (apr_pkt_priv->pkt_owner == APR_PKT_OWNER_DRIVER) {
85 tx_buf = container_of((void *)apr_pkt_priv,
86 struct apr_tx_buf, pkt_priv);
87 pr_debug("%s: Freeing buffer %pK", __func__, tx_buf);
88 kfree(tx_buf);
89 }
90}
91
92
93static int __apr_tal_write(struct apr_svc_ch_dev *apr_ch, void *data,
94 struct apr_pkt_priv *pkt_priv, int len)
95{
96 int rc = 0;
97 unsigned long flags;
98
99 spin_lock_irqsave(&apr_ch->w_lock, flags);
100 rc = glink_tx(apr_ch->handle, pkt_priv, data, len, GLINK_TX_ATOMIC);
101 spin_unlock_irqrestore(&apr_ch->w_lock, flags);
102
103 if (rc)
104 pr_err("%s: glink_tx failed, rc[%d]\n", __func__, rc);
105 else
106 rc = len;
107
108 return rc;
109}
110
111int apr_tal_write(struct apr_svc_ch_dev *apr_ch, void *data,
112 struct apr_pkt_priv *pkt_priv, int len)
113{
114 int rc = 0, retries = 0;
115 void *pkt_data = NULL;
116 struct apr_tx_buf *tx_buf = NULL;
117 struct apr_pkt_priv *pkt_priv_ptr = pkt_priv;
118
119 if (!apr_ch->handle || !pkt_priv)
120 return -EINVAL;
121
122 if (pkt_priv->pkt_owner == APR_PKT_OWNER_DRIVER) {
123 tx_buf = apr_alloc_buf(len);
124 if (IS_ERR_OR_NULL(tx_buf)) {
125 rc = -EINVAL;
126 goto exit;
127 }
128 memcpy(tx_buf->buf, data, len);
129 memcpy(&tx_buf->pkt_priv, pkt_priv, sizeof(tx_buf->pkt_priv));
130 pkt_priv_ptr = &tx_buf->pkt_priv;
131 pkt_data = tx_buf->buf;
132 } else {
133 pkt_data = data;
134 }
135
136 do {
137 if (rc == -EAGAIN)
138 udelay(50);
139
140 rc = __apr_tal_write(apr_ch, pkt_data, pkt_priv_ptr, len);
141 } while (rc == -EAGAIN && retries++ < APR_MAXIMUM_NUM_OF_RETRIES);
142
143 if (rc < 0) {
144 pr_err("%s: Unable to send the packet, rc:%d\n", __func__, rc);
145 if (pkt_priv->pkt_owner == APR_PKT_OWNER_DRIVER)
146 kfree(tx_buf);
147 }
148exit:
149 return rc;
150}
151
152void apr_tal_notify_rx(void *handle, const void *priv, const void *pkt_priv,
153 const void *ptr, size_t size)
154{
155 struct apr_svc_ch_dev *apr_ch = (struct apr_svc_ch_dev *)priv;
156 unsigned long flags;
157
158 if (!apr_ch || !ptr) {
159 pr_err("%s: Invalid apr_ch or ptr\n", __func__);
160 return;
161 }
162
163 pr_debug("%s: Rx packet received\n", __func__);
164
165 spin_lock_irqsave(&apr_ch->r_lock, flags);
166 if (apr_ch->func)
167 apr_ch->func((void *)ptr, size, (void *)pkt_priv);
168 spin_unlock_irqrestore(&apr_ch->r_lock, flags);
169 glink_rx_done(apr_ch->handle, ptr, true);
170}
171
172static void apr_tal_notify_tx_abort(void *handle, const void *priv,
173 const void *pkt_priv)
174{
175 pr_debug("%s: tx_abort received for pkt_priv:%pK\n",
176 __func__, pkt_priv);
177 apr_free_buf(pkt_priv);
178}
179
180void apr_tal_notify_tx_done(void *handle, const void *priv,
181 const void *pkt_priv, const void *ptr)
182{
183 pr_debug("%s: tx_done received for pkt_priv:%pK\n",
184 __func__, pkt_priv);
185 apr_free_buf(pkt_priv);
186}
187
188bool apr_tal_notify_rx_intent_req(void *handle, const void *priv,
189 size_t req_size)
190{
191 struct apr_svc_ch_dev *apr_ch = (struct apr_svc_ch_dev *)priv;
192
193 if (!apr_ch) {
194 pr_err("%s: Invalid apr_ch\n", __func__);
195 return false;
196 }
197
198 pr_err("%s: No rx intents queued, unable to receive\n", __func__);
199 return false;
200}
201
202static void apr_tal_notify_remote_rx_intent(void *handle, const void *priv,
203 size_t size)
204{
205 struct apr_svc_ch_dev *apr_ch = (struct apr_svc_ch_dev *)priv;
206
207 if (!apr_ch) {
208 pr_err("%s: Invalid apr_ch\n", __func__);
209 return;
210 }
211 /*
212 * This is to make sure that the far end has queued at least one intent
213 * before we attmpt any IPC. A simple bool flag is used here instead of
214 * a counter, as the far end is required to guarantee intent
215 * availability for all use cases once the channel is fully opened.
216 */
217 pr_debug("%s: remote queued an intent\n", __func__);
218 apr_ch->if_remote_intent_ready = true;
219 wake_up(&apr_ch->wait);
220}
221
222void apr_tal_notify_state(void *handle, const void *priv, unsigned int event)
223{
224 struct apr_svc_ch_dev *apr_ch = (struct apr_svc_ch_dev *)priv;
225
226 if (!apr_ch) {
227 pr_err("%s: Invalid apr_ch\n", __func__);
228 return;
229 }
230
231 apr_ch->channel_state = event;
232 pr_info("%s: Channel state[%d]\n", __func__, event);
233
234 if (event == GLINK_CONNECTED)
235 wake_up(&apr_ch->wait);
236}
237
238int apr_tal_rx_intents_config(struct apr_svc_ch_dev *apr_ch,
239 int num_of_intents, uint32_t size)
240{
241 int i;
Laxminath Kasam8f7ccc22017-08-28 17:35:04 +0530242 int rc = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530243
244 if (!apr_ch || !num_of_intents || !size) {
245 pr_err("%s: Invalid parameter\n", __func__);
246 return -EINVAL;
247 }
248
249 for (i = 0; i < num_of_intents; i++) {
250 rc = glink_queue_rx_intent(apr_ch->handle, apr_ch, size);
251 if (rc) {
252 pr_err("%s: Failed to queue rx intent, iteration[%d]\n",
253 __func__, i);
254 break;
255 }
256 }
257
258 return rc;
259}
260
261struct apr_svc_ch_dev *apr_tal_open(uint32_t clnt, uint32_t dest, uint32_t dl,
262 apr_svc_cb_fn func, void *priv)
263{
264 int rc;
265 struct glink_open_config open_cfg;
266 struct apr_svc_ch_dev *apr_ch;
267
268 if ((clnt >= APR_CLIENT_MAX) || (dest >= APR_DEST_MAX) ||
269 (dl >= APR_DL_MAX)) {
270 pr_err("%s: Invalid params, clnt:%d, dest:%d, dl:%d\n",
271 __func__, clnt, dest, dl);
272 return NULL;
273 }
274
275 apr_ch = &apr_svc_ch[dl][dest][clnt];
276 mutex_lock(&apr_ch->m_lock);
277 if (apr_ch->handle) {
278 pr_err("%s: This channel is already opened\n", __func__);
279 rc = -EBUSY;
280 goto unlock;
281 }
282
283 if (link_state[dest].link_state != GLINK_LINK_STATE_UP) {
284 rc = wait_event_timeout(link_state[dest].wait,
285 link_state[dest].link_state == GLINK_LINK_STATE_UP,
286 msecs_to_jiffies(APR_OPEN_TIMEOUT_MS));
287 if (rc == 0) {
288 pr_err("%s: Open timeout, dest:%d\n", __func__, dest);
289 rc = -ETIMEDOUT;
290 goto unlock;
291 }
292 pr_debug("%s: Wakeup done, dest:%d\n", __func__, dest);
293 }
294
295 memset(&open_cfg, 0, sizeof(struct glink_open_config));
296 open_cfg.options = GLINK_OPT_INITIAL_XPORT;
297 if (dest == APR_DEST_MODEM)
298 open_cfg.edge = "mpss";
299 else
300 open_cfg.edge = "lpass";
301
302 open_cfg.name = svc_names[dest][clnt];
303 open_cfg.notify_rx = apr_tal_notify_rx;
304 open_cfg.notify_tx_done = apr_tal_notify_tx_done;
305 open_cfg.notify_state = apr_tal_notify_state;
306 open_cfg.notify_rx_intent_req = apr_tal_notify_rx_intent_req;
307 open_cfg.notify_remote_rx_intent = apr_tal_notify_remote_rx_intent;
308 open_cfg.notify_tx_abort = apr_tal_notify_tx_abort;
309 open_cfg.priv = apr_ch;
310 open_cfg.transport = "smem";
311
312 apr_ch->channel_state = GLINK_REMOTE_DISCONNECTED;
313 apr_ch->handle = glink_open(&open_cfg);
314 if (IS_ERR_OR_NULL(apr_ch->handle)) {
315 pr_err("%s: glink_open failed %s\n", __func__,
316 svc_names[dest][clnt]);
317 apr_ch->handle = NULL;
318 rc = -EINVAL;
319 goto unlock;
320 }
321
322 rc = wait_event_timeout(apr_ch->wait,
323 (apr_ch->channel_state == GLINK_CONNECTED), 5 * HZ);
324 if (rc == 0) {
325 pr_err("%s: TIMEOUT for OPEN event\n", __func__);
326 rc = -ETIMEDOUT;
327 goto close_link;
328 }
329
330 /*
331 * Remote intent is not required for GLINK <--> SMD IPC, so this is
332 * designed not to fail the open call.
333 */
334 rc = wait_event_timeout(apr_ch->wait,
335 apr_ch->if_remote_intent_ready, 5 * HZ);
336 if (rc == 0)
337 pr_err("%s: TIMEOUT for remote intent readiness\n", __func__);
338
339 rc = apr_tal_rx_intents_config(apr_ch, APR_DEFAULT_NUM_OF_INTENTS,
340 APR_MAX_BUF);
341 if (rc) {
342 pr_err("%s: Unable to queue intents\n", __func__);
343 goto close_link;
344 }
345
346 apr_ch->func = func;
347 apr_ch->priv = priv;
348
349close_link:
350 if (rc) {
351 glink_close(apr_ch->handle);
352 apr_ch->handle = NULL;
353 }
354unlock:
355 mutex_unlock(&apr_ch->m_lock);
356
357 return rc ? NULL : apr_ch;
358}
359
Banajit Goswami88327322017-12-08 10:51:58 -0800360int apr_tal_start_rx_rt(struct apr_svc_ch_dev *apr_ch)
361{
362 int rc = 0;
363
364 if (!apr_ch || !apr_ch->handle) {
365 rc = -EINVAL;
366 goto exit;
367 }
368
369 mutex_lock(&apr_ch->m_lock);
370 rc = glink_start_rx_rt(apr_ch->handle);
371 mutex_unlock(&apr_ch->m_lock);
372exit:
373 return rc;
374}
375
376int apr_tal_end_rx_rt(struct apr_svc_ch_dev *apr_ch)
377{
378 int rc = 0;
379
380 if (!apr_ch || !apr_ch->handle) {
381 rc = -EINVAL;
382 goto exit;
383 }
384
385 mutex_lock(&apr_ch->m_lock);
386 rc = glink_end_rx_rt(apr_ch->handle);
387 mutex_unlock(&apr_ch->m_lock);
388exit:
389 return rc;
390}
391
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530392int apr_tal_close(struct apr_svc_ch_dev *apr_ch)
393{
394 int rc;
395
396 if (!apr_ch || !apr_ch->handle) {
397 rc = -EINVAL;
398 goto exit;
399 }
400
401 mutex_lock(&apr_ch->m_lock);
402 rc = glink_close(apr_ch->handle);
403 apr_ch->handle = NULL;
404 apr_ch->func = NULL;
405 apr_ch->priv = NULL;
406 apr_ch->if_remote_intent_ready = false;
407 mutex_unlock(&apr_ch->m_lock);
408exit:
409 return rc;
410}
411
412static void apr_tal_link_state_cb(struct glink_link_state_cb_info *cb_info,
413 void *priv)
414{
415 uint32_t dest;
416
417 if (!cb_info) {
418 pr_err("%s: Invalid cb_info\n", __func__);
419 return;
420 }
421
422 if (!strcmp(cb_info->edge, "mpss"))
423 dest = APR_DEST_MODEM;
424 else if (!strcmp(cb_info->edge, "lpass"))
425 dest = APR_DEST_QDSP6;
426 else {
427 pr_err("%s:Unknown edge[%s]\n", __func__, cb_info->edge);
428 return;
429 }
430
431 pr_info("%s: edge[%s] link state[%d]\n", __func__, cb_info->edge,
432 cb_info->link_state);
433
434 link_state[dest].link_state = cb_info->link_state;
435 if (link_state[dest].link_state == GLINK_LINK_STATE_UP)
436 wake_up(&link_state[dest].wait);
437}
438
439static struct glink_link_info mpss_link_info = {
440 .transport = "smem",
441 .edge = "mpss",
442 .glink_link_state_notif_cb = apr_tal_link_state_cb,
443};
444
445static struct glink_link_info lpass_link_info = {
446 .transport = "smem",
447 .edge = "lpass",
448 .glink_link_state_notif_cb = apr_tal_link_state_cb,
449};
450
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530451int apr_tal_init(void)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530452{
453 int i, j, k;
454
455 for (i = 0; i < APR_DL_MAX; i++) {
456 for (j = 0; j < APR_DEST_MAX; j++) {
457 for (k = 0; k < APR_CLIENT_MAX; k++) {
458 init_waitqueue_head(&apr_svc_ch[i][j][k].wait);
459 spin_lock_init(&apr_svc_ch[i][j][k].w_lock);
460 spin_lock_init(&apr_svc_ch[i][j][k].r_lock);
461 mutex_init(&apr_svc_ch[i][j][k].m_lock);
462 }
463 }
464 }
465
466 for (i = 0; i < APR_DEST_MAX; i++)
467 init_waitqueue_head(&link_state[i].wait);
468
469 link_state[APR_DEST_MODEM].link_state = GLINK_LINK_STATE_DOWN;
470 link_state[APR_DEST_MODEM].handle =
471 glink_register_link_state_cb(&mpss_link_info, NULL);
472 if (!link_state[APR_DEST_MODEM].handle)
473 pr_err("%s: Unable to register mpss link state\n", __func__);
474
475 link_state[APR_DEST_QDSP6].link_state = GLINK_LINK_STATE_DOWN;
476 link_state[APR_DEST_QDSP6].handle =
477 glink_register_link_state_cb(&lpass_link_info, NULL);
478 if (!link_state[APR_DEST_QDSP6].handle)
479 pr_err("%s: Unable to register lpass link state\n", __func__);
480
481 return 0;
482}