blob: cab7c3b7c4a27db4f1a45e473adba2fcd771b2d8 [file] [log] [blame]
Laxminath Kasamd1f36192017-08-03 18:54:01 +05301/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#include <linux/init.h>
14#include <linux/kernel.h>
15#include <linux/module.h>
16#include <linux/mutex.h>
17#include <linux/errno.h>
18#include <linux/fs.h>
19#include <linux/uaccess.h>
20#include <linux/slab.h>
21#include <linux/list.h>
22#include <linux/cdev.h>
23#include <linux/platform_device.h>
24#include <linux/vmalloc.h>
25#include <soc/qcom/glink.h>
26#include "sound/wcd-dsp-glink.h"
27
28#define WDSP_GLINK_DRIVER_NAME "wcd-dsp-glink"
29#define WDSP_MAX_WRITE_SIZE (256 * 1024)
30#define WDSP_MAX_READ_SIZE (4 * 1024)
31#define WDSP_MAX_NO_OF_INTENTS (20)
32#define WDSP_MAX_NO_OF_CHANNELS (10)
33#define WDSP_WRITE_PKT_SIZE (sizeof(struct wdsp_write_pkt))
34#define WDSP_REG_PKT_SIZE (sizeof(struct wdsp_reg_pkt))
35#define WDSP_CMD_PKT_SIZE (sizeof(struct wdsp_cmd_pkt))
36#define WDSP_CH_CFG_SIZE (sizeof(struct wdsp_glink_ch_cfg))
37
38#define MINOR_NUMBER_COUNT 1
39#define WDSP_EDGE "wdsp"
40#define RESP_QUEUE_SIZE 3
41#define QOS_PKT_SIZE 1024
42#define TIMEOUT_MS 1000
43
44struct wdsp_glink_dev {
45 struct class *cls;
46 struct device *dev;
47 struct cdev cdev;
48 dev_t dev_num;
49};
50
51struct wdsp_glink_rsp_que {
52 /* Size of valid data in buffer */
53 u32 buf_size;
54
55 /* Response buffer */
56 u8 buf[WDSP_MAX_READ_SIZE];
57};
58
59struct wdsp_glink_tx_buf {
60 struct work_struct tx_work;
61 struct work_struct free_tx_work;
62
63 /* Glink channel information */
64 struct wdsp_glink_ch *ch;
65
66 /* Tx buffer to send to glink */
67 u8 buf[0];
68};
69
70struct wdsp_glink_ch {
71 struct wdsp_glink_priv *wpriv;
72
73 /* Glink channel handle */
74 void *handle;
75
76 /* Channel states like connect, disconnect */
77 int channel_state;
78 struct mutex mutex;
79
80 /* To free up the channel memory */
81 bool free_mem;
82
83 /* Glink local channel open work */
84 struct work_struct lcl_ch_open_wrk;
85
86 /* Glink local channel close work */
87 struct work_struct lcl_ch_cls_wrk;
88
89 /* Wait for ch connect state before sending any command */
90 wait_queue_head_t ch_connect_wait;
91
92 /*
93 * Glink channel configuration. This has to be the last
94 * member of the strucuture as it has variable size
95 */
96 struct wdsp_glink_ch_cfg ch_cfg;
97};
98
99struct wdsp_glink_state {
100 /* Glink link state information */
101 enum glink_link_state link_state;
102 void *handle;
103};
104
105struct wdsp_glink_priv {
106 /* Respone buffer related */
107 u8 rsp_cnt;
108 struct wdsp_glink_rsp_que rsp[RESP_QUEUE_SIZE];
109 struct completion rsp_complete;
110 struct mutex rsp_mutex;
111
112 /* Glink channel related */
113 struct mutex glink_mutex;
114 struct wdsp_glink_state glink_state;
115 struct wdsp_glink_ch **ch;
116 u8 no_of_channels;
117 struct work_struct ch_open_cls_wrk;
118 struct workqueue_struct *work_queue;
119
120 wait_queue_head_t link_state_wait;
121
122 struct device *dev;
123};
124
125static int wdsp_glink_close_ch(struct wdsp_glink_ch *ch);
126static int wdsp_glink_open_ch(struct wdsp_glink_ch *ch);
127
128/*
129 * wdsp_glink_free_tx_buf_work - Work function to free tx pkt
130 * work: Work structure
131 */
132static void wdsp_glink_free_tx_buf_work(struct work_struct *work)
133{
134 struct wdsp_glink_tx_buf *tx_buf;
135
136 tx_buf = container_of(work, struct wdsp_glink_tx_buf,
137 free_tx_work);
138 vfree(tx_buf);
139}
140
141/*
142 * wdsp_glink_free_tx_buf - Function to free tx buffer
143 * priv: Pointer to the channel
144 * pkt_priv: Pointer to the tx buffer
145 */
146static void wdsp_glink_free_tx_buf(const void *priv, const void *pkt_priv)
147{
148 struct wdsp_glink_tx_buf *tx_buf = (struct wdsp_glink_tx_buf *)pkt_priv;
149 struct wdsp_glink_priv *wpriv;
150 struct wdsp_glink_ch *ch;
151
152 if (!priv) {
153 pr_err("%s: Invalid priv\n", __func__);
154 return;
155 }
156 if (!tx_buf) {
157 pr_err("%s: Invalid tx_buf\n", __func__);
158 return;
159 }
160
161 ch = (struct wdsp_glink_ch *)priv;
162 wpriv = ch->wpriv;
163 /* Work queue to free tx pkt */
164 INIT_WORK(&tx_buf->free_tx_work, wdsp_glink_free_tx_buf_work);
165 queue_work(wpriv->work_queue, &tx_buf->free_tx_work);
166}
167
168/*
169 * wdsp_glink_notify_rx - Glink notify rx callback for responses
170 * handle: Opaque Channel handle returned by GLink
171 * priv: Private pointer to the channel
172 * pkt_priv: Private pointer to the packet
173 * ptr: Pointer to the Rx data
174 * size: Size of the Rx data
175 */
176static void wdsp_glink_notify_rx(void *handle, const void *priv,
177 const void *pkt_priv, const void *ptr,
178 size_t size)
179{
180 u8 *rx_buf;
181 u8 rsp_cnt;
182 struct wdsp_glink_ch *ch;
183 struct wdsp_glink_priv *wpriv;
184
185 if (!ptr || !priv) {
186 pr_err("%s: Invalid parameters\n", __func__);
187 return;
188 }
189
190 ch = (struct wdsp_glink_ch *)priv;
191 wpriv = ch->wpriv;
192 rx_buf = (u8 *)ptr;
193 if (size > WDSP_MAX_READ_SIZE) {
194 dev_err(wpriv->dev, "%s: Size %zd is greater than allowed %d\n",
195 __func__, size, WDSP_MAX_READ_SIZE);
196 size = WDSP_MAX_READ_SIZE;
197 }
198
199 mutex_lock(&wpriv->rsp_mutex);
200 rsp_cnt = wpriv->rsp_cnt;
201 if (rsp_cnt >= RESP_QUEUE_SIZE) {
202 dev_err(wpriv->dev, "%s: Resp Queue is Full\n", __func__);
203 rsp_cnt = 0;
204 }
205 dev_dbg(wpriv->dev, "%s: copy into buffer %d\n", __func__, rsp_cnt);
206
207 memcpy(wpriv->rsp[rsp_cnt].buf, rx_buf, size);
208 wpriv->rsp[rsp_cnt].buf_size = size;
209 wpriv->rsp_cnt = ++rsp_cnt;
210 mutex_unlock(&wpriv->rsp_mutex);
211
212 glink_rx_done(handle, ptr, true);
213 complete(&wpriv->rsp_complete);
214}
215
216/*
217 * wdsp_glink_notify_tx_done - Glink notify tx done callback to
218 * free tx buffer
219 * handle: Opaque Channel handle returned by GLink
220 * priv: Private pointer to the channel
221 * pkt_priv: Private pointer to the packet
222 * ptr: Pointer to the Tx data
223 */
224static void wdsp_glink_notify_tx_done(void *handle, const void *priv,
225 const void *pkt_priv, const void *ptr)
226{
227 wdsp_glink_free_tx_buf(priv, pkt_priv);
228}
229/*
230 * wdsp_glink_notify_tx_abort - Glink notify tx abort callback to
231 * free tx buffer
232 * handle: Opaque Channel handle returned by GLink
233 * priv: Private pointer to the channel
234 * pkt_priv: Private pointer to the packet
235 */
236static void wdsp_glink_notify_tx_abort(void *handle, const void *priv,
237 const void *pkt_priv)
238{
239 wdsp_glink_free_tx_buf(priv, pkt_priv);
240}
241
242/*
243 * wdsp_glink_notify_rx_intent_req - Glink notify rx intent request callback
244 * to queue buffer to receive from remote client
245 * handle: Opaque channel handle returned by GLink
246 * priv: Private pointer to the channel
247 * req_size: Size of intent to be queued
248 */
249static bool wdsp_glink_notify_rx_intent_req(void *handle, const void *priv,
250 size_t req_size)
251{
252 struct wdsp_glink_priv *wpriv;
253 struct wdsp_glink_ch *ch;
254 int rc = 0;
255 bool ret = false;
256
257 if (!priv) {
258 pr_err("%s: Invalid priv\n", __func__);
259 goto done;
260 }
261 if (req_size > WDSP_MAX_READ_SIZE) {
262 pr_err("%s: Invalid req_size %zd\n", __func__, req_size);
263 goto done;
264 }
265
266 ch = (struct wdsp_glink_ch *)priv;
267 wpriv = ch->wpriv;
268
269 dev_dbg(wpriv->dev, "%s: intent size %zd requested for ch name %s",
270 __func__, req_size, ch->ch_cfg.name);
271
272 mutex_lock(&ch->mutex);
273 rc = glink_queue_rx_intent(ch->handle, ch, req_size);
274 if (rc < 0) {
275 dev_err(wpriv->dev, "%s: Failed to queue rx intent, rc = %d\n",
276 __func__, rc);
277 mutex_unlock(&ch->mutex);
278 goto done;
279 }
280 mutex_unlock(&ch->mutex);
281 ret = true;
282
283done:
284 return ret;
285}
286
287/*
288 * wdsp_glink_lcl_ch_open_wrk - Work function to open channel again
289 * when local disconnect event happens
290 * work: Work structure
291 */
292static void wdsp_glink_lcl_ch_open_wrk(struct work_struct *work)
293{
294 struct wdsp_glink_ch *ch;
295
296 ch = container_of(work, struct wdsp_glink_ch,
297 lcl_ch_open_wrk);
298
299 wdsp_glink_open_ch(ch);
300}
301
302/*
303 * wdsp_glink_lcl_ch_cls_wrk - Work function to close channel locally
304 * when remote disconnect event happens
305 * work: Work structure
306 */
307static void wdsp_glink_lcl_ch_cls_wrk(struct work_struct *work)
308{
309 struct wdsp_glink_ch *ch;
310
311 ch = container_of(work, struct wdsp_glink_ch,
312 lcl_ch_cls_wrk);
313
314 wdsp_glink_close_ch(ch);
315}
316
317/*
318 * wdsp_glink_notify_state - Glink channel state information event callback
319 * handle: Opaque Channel handle returned by GLink
320 * priv: Private pointer to the channel
321 * event: channel state event
322 */
323static void wdsp_glink_notify_state(void *handle, const void *priv,
324 unsigned int event)
325{
326 struct wdsp_glink_priv *wpriv;
327 struct wdsp_glink_ch *ch;
328 int i, ret = 0;
329
330 if (!priv) {
331 pr_err("%s: Invalid priv\n", __func__);
332 return;
333 }
334
335 ch = (struct wdsp_glink_ch *)priv;
336 wpriv = ch->wpriv;
337
338 mutex_lock(&ch->mutex);
339 ch->channel_state = event;
340 if (event == GLINK_CONNECTED) {
341 dev_dbg(wpriv->dev, "%s: glink channel: %s connected\n",
342 __func__, ch->ch_cfg.name);
343
344 for (i = 0; i < ch->ch_cfg.no_of_intents; i++) {
345 dev_dbg(wpriv->dev, "%s: intent_size = %d\n", __func__,
346 ch->ch_cfg.intents_size[i]);
347 ret = glink_queue_rx_intent(ch->handle, ch,
348 ch->ch_cfg.intents_size[i]);
349 if (ret < 0)
350 dev_warn(wpriv->dev, "%s: Failed to queue intent %d of size %d\n",
351 __func__, i,
352 ch->ch_cfg.intents_size[i]);
353 }
354
355 ret = glink_qos_latency(ch->handle, ch->ch_cfg.latency_in_us,
356 QOS_PKT_SIZE);
357 if (ret < 0)
358 dev_warn(wpriv->dev, "%s: Failed to request qos %d for ch %s\n",
359 __func__, ch->ch_cfg.latency_in_us,
360 ch->ch_cfg.name);
361
362 wake_up(&ch->ch_connect_wait);
363 mutex_unlock(&ch->mutex);
364 } else if (event == GLINK_LOCAL_DISCONNECTED) {
365 /*
366 * Don't use dev_dbg here as dev may not be valid if channel
367 * closed from driver close.
368 */
369 pr_debug("%s: channel: %s disconnected locally\n",
370 __func__, ch->ch_cfg.name);
371 mutex_unlock(&ch->mutex);
372
373 if (ch->free_mem) {
374 kfree(ch);
375 ch = NULL;
376 }
377 } else if (event == GLINK_REMOTE_DISCONNECTED) {
378 dev_dbg(wpriv->dev, "%s: remote channel: %s disconnected remotely\n",
379 __func__, ch->ch_cfg.name);
380 mutex_unlock(&ch->mutex);
381 /*
382 * If remote disconnect happens, local side also has
383 * to close the channel as per glink design in a
384 * separate work_queue.
385 */
386 queue_work(wpriv->work_queue, &ch->lcl_ch_cls_wrk);
387 }
388}
389
390/*
391 * wdsp_glink_close_ch - Internal function to close glink channel
392 * ch: Glink Channel structure.
393 */
394static int wdsp_glink_close_ch(struct wdsp_glink_ch *ch)
395{
396 struct wdsp_glink_priv *wpriv = ch->wpriv;
397 int ret = 0;
398
399 mutex_lock(&wpriv->glink_mutex);
400 if (ch->handle) {
401 ret = glink_close(ch->handle);
402 if (ret < 0) {
403 dev_err(wpriv->dev, "%s: glink_close is failed, ret = %d\n",
404 __func__, ret);
405 } else {
406 ch->handle = NULL;
407 dev_dbg(wpriv->dev, "%s: ch %s is closed\n", __func__,
408 ch->ch_cfg.name);
409 }
410 } else {
411 dev_dbg(wpriv->dev, "%s: ch %s is already closed\n", __func__,
412 ch->ch_cfg.name);
413 }
414 mutex_unlock(&wpriv->glink_mutex);
415
416
417 return ret;
418}
419
420/*
421 * wdsp_glink_open_ch - Internal function to open glink channel
422 * ch: Glink Channel structure.
423 */
424static int wdsp_glink_open_ch(struct wdsp_glink_ch *ch)
425{
426 struct wdsp_glink_priv *wpriv = ch->wpriv;
427 struct glink_open_config open_cfg;
428 int ret = 0;
429
430 mutex_lock(&wpriv->glink_mutex);
431 if (!ch->handle) {
432 memset(&open_cfg, 0, sizeof(open_cfg));
433 open_cfg.options = GLINK_OPT_INITIAL_XPORT;
434 open_cfg.edge = WDSP_EDGE;
435 open_cfg.notify_rx = wdsp_glink_notify_rx;
436 open_cfg.notify_tx_done = wdsp_glink_notify_tx_done;
437 open_cfg.notify_tx_abort = wdsp_glink_notify_tx_abort;
438 open_cfg.notify_state = wdsp_glink_notify_state;
439 open_cfg.notify_rx_intent_req = wdsp_glink_notify_rx_intent_req;
440 open_cfg.priv = ch;
441 open_cfg.name = ch->ch_cfg.name;
442
443 dev_dbg(wpriv->dev, "%s: ch->ch_cfg.name = %s, latency_in_us = %d, intents = %d\n",
444 __func__, ch->ch_cfg.name, ch->ch_cfg.latency_in_us,
445 ch->ch_cfg.no_of_intents);
446
447 ch->handle = glink_open(&open_cfg);
448 if (IS_ERR_OR_NULL(ch->handle)) {
449 dev_err(wpriv->dev, "%s: glink_open failed for ch %s\n",
450 __func__, ch->ch_cfg.name);
451 ch->handle = NULL;
452 ret = -EINVAL;
453 }
454 } else {
455 dev_err(wpriv->dev, "%s: ch %s is already opened\n", __func__,
456 ch->ch_cfg.name);
457 }
458 mutex_unlock(&wpriv->glink_mutex);
459
460 return ret;
461}
462
463/*
464 * wdsp_glink_close_all_ch - Internal function to close all glink channels
465 * wpriv: Wdsp_glink private structure
466 */
467static void wdsp_glink_close_all_ch(struct wdsp_glink_priv *wpriv)
468{
469 int i;
470
471 for (i = 0; i < wpriv->no_of_channels; i++)
472 if (wpriv->ch && wpriv->ch[i])
473 wdsp_glink_close_ch(wpriv->ch[i]);
474}
475
476/*
477 * wdsp_glink_open_all_ch - Internal function to open all glink channels
478 * wpriv: Wdsp_glink private structure
479 */
480static int wdsp_glink_open_all_ch(struct wdsp_glink_priv *wpriv)
481{
482 int ret = 0, i, j;
483
484 for (i = 0; i < wpriv->no_of_channels; i++) {
485 if (wpriv->ch && wpriv->ch[i]) {
486 ret = wdsp_glink_open_ch(wpriv->ch[i]);
487 if (ret < 0)
488 goto err_open;
489 }
490 }
491 goto done;
492
493err_open:
494 for (j = 0; j < i; j++)
495 if (wpriv->ch[i])
496 wdsp_glink_close_ch(wpriv->ch[j]);
497
498done:
499 return ret;
500}
501
502/*
503 * wdsp_glink_ch_open_wq - Work function to open glink channels
504 * work: Work structure
505 */
506static void wdsp_glink_ch_open_cls_wrk(struct work_struct *work)
507{
508 struct wdsp_glink_priv *wpriv;
509
510 wpriv = container_of(work, struct wdsp_glink_priv,
511 ch_open_cls_wrk);
512
513 if (wpriv->glink_state.link_state == GLINK_LINK_STATE_DOWN) {
514 dev_info(wpriv->dev, "%s: GLINK_LINK_STATE_DOWN\n",
515 __func__);
516
517 wdsp_glink_close_all_ch(wpriv);
518 } else if (wpriv->glink_state.link_state == GLINK_LINK_STATE_UP) {
519 dev_info(wpriv->dev, "%s: GLINK_LINK_STATE_UP\n",
520 __func__);
521
522 wdsp_glink_open_all_ch(wpriv);
523 }
524}
525
526/*
527 * wdsp_glink_link_state_cb - Glink link state callback to inform
528 * about link states
529 * cb_info: Glink link state callback information structure
530 * priv: Private structure of link state passed while register
531 */
532static void wdsp_glink_link_state_cb(struct glink_link_state_cb_info *cb_info,
533 void *priv)
534{
535 struct wdsp_glink_priv *wpriv;
536
537 if (!cb_info || !priv) {
538 pr_err("%s: Invalid parameters\n", __func__);
539 return;
540 }
541
542 wpriv = (struct wdsp_glink_priv *)priv;
543
544 mutex_lock(&wpriv->glink_mutex);
545 wpriv->glink_state.link_state = cb_info->link_state;
546 wake_up(&wpriv->link_state_wait);
547 mutex_unlock(&wpriv->glink_mutex);
548
549 queue_work(wpriv->work_queue, &wpriv->ch_open_cls_wrk);
550}
551
552/*
553 * wdsp_glink_ch_info_init- Internal function to allocate channel memory
554 * and register with glink
555 * wpriv: Wdsp_glink private structure.
556 * pkt: Glink registration packet contains glink channel information.
557 * pkt_size: Size of the pkt.
558 */
559static int wdsp_glink_ch_info_init(struct wdsp_glink_priv *wpriv,
560 struct wdsp_reg_pkt *pkt, size_t pkt_size)
561{
562 int ret = 0, i, j;
563 struct glink_link_info link_info;
564 struct wdsp_glink_ch_cfg *ch_cfg;
565 struct wdsp_glink_ch **ch;
566 u8 no_of_channels;
567 u8 *payload;
568 u32 ch_size, ch_cfg_size;
569 size_t size = WDSP_WRITE_PKT_SIZE + WDSP_REG_PKT_SIZE;
570
571 mutex_lock(&wpriv->glink_mutex);
572 if (wpriv->ch) {
Vidyakumar Athota60871bd2017-09-08 11:26:51 -0700573 dev_err_ratelimited(wpriv->dev, "%s: glink ch memory is already allocated\n",
Laxminath Kasamd1f36192017-08-03 18:54:01 +0530574 __func__);
575 ret = -EINVAL;
576 goto done;
577 }
578 payload = (u8 *)pkt->payload;
579 no_of_channels = pkt->no_of_channels;
580
581 if (no_of_channels > WDSP_MAX_NO_OF_CHANNELS) {
Vidyakumar Athota60871bd2017-09-08 11:26:51 -0700582 dev_err_ratelimited(wpriv->dev, "%s: no_of_channels: %d but max allowed are %d\n",
Laxminath Kasamd1f36192017-08-03 18:54:01 +0530583 __func__, no_of_channels, WDSP_MAX_NO_OF_CHANNELS);
584 ret = -EINVAL;
585 goto done;
586 }
587 ch = kcalloc(no_of_channels, sizeof(struct wdsp_glink_ch *),
588 GFP_ATOMIC);
589 if (!ch) {
590 ret = -ENOMEM;
591 goto done;
592 }
593 wpriv->ch = ch;
594 wpriv->no_of_channels = no_of_channels;
595
596 for (i = 0; i < no_of_channels; i++) {
597 ch_cfg = (struct wdsp_glink_ch_cfg *)payload;
598
599 size += WDSP_CH_CFG_SIZE;
600 if (size > pkt_size) {
Vidyakumar Athota60871bd2017-09-08 11:26:51 -0700601 dev_err_ratelimited(wpriv->dev, "%s: Invalid size = %zd, pkt_size = %zd\n",
Laxminath Kasamd1f36192017-08-03 18:54:01 +0530602 __func__, size, pkt_size);
603 ret = -EINVAL;
604 goto err_ch_mem;
605 }
606 if (ch_cfg->no_of_intents > WDSP_MAX_NO_OF_INTENTS) {
Vidyakumar Athota60871bd2017-09-08 11:26:51 -0700607 dev_err_ratelimited(wpriv->dev, "%s: Invalid no_of_intents = %d\n",
Laxminath Kasamd1f36192017-08-03 18:54:01 +0530608 __func__, ch_cfg->no_of_intents);
609 ret = -EINVAL;
610 goto err_ch_mem;
611 }
612 size += (sizeof(u32) * ch_cfg->no_of_intents);
613 if (size > pkt_size) {
Vidyakumar Athota60871bd2017-09-08 11:26:51 -0700614 dev_err_ratelimited(wpriv->dev, "%s: Invalid size = %zd, pkt_size = %zd\n",
Laxminath Kasamd1f36192017-08-03 18:54:01 +0530615 __func__, size, pkt_size);
616 ret = -EINVAL;
617 goto err_ch_mem;
618 }
619
620 ch_cfg_size = sizeof(struct wdsp_glink_ch_cfg) +
621 (sizeof(u32) * ch_cfg->no_of_intents);
622 ch_size = sizeof(struct wdsp_glink_ch) +
623 (sizeof(u32) * ch_cfg->no_of_intents);
624
625 dev_dbg(wpriv->dev, "%s: channels: %d ch_cfg_size: %d, size: %zd, pkt_size: %zd",
626 __func__, no_of_channels, ch_cfg_size, size, pkt_size);
627
628 ch[i] = kzalloc(ch_size, GFP_KERNEL);
629 if (!ch[i]) {
630 ret = -ENOMEM;
631 goto err_ch_mem;
632 }
633 ch[i]->channel_state = GLINK_LOCAL_DISCONNECTED;
634 memcpy(&ch[i]->ch_cfg, payload, ch_cfg_size);
635 payload += ch_cfg_size;
636
Vidyakumar Athota87c83b72017-09-19 12:06:46 -0700637 /* check ch name is valid string or not */
638 for (j = 0; j < WDSP_CH_NAME_MAX_LEN; j++) {
639 if (ch[i]->ch_cfg.name[j] == '\0')
640 break;
641 }
642
643 if (j == WDSP_CH_NAME_MAX_LEN) {
644 dev_err_ratelimited(wpriv->dev, "%s: Wrong channel name\n",
645 __func__);
646 kfree(ch[i]);
647 ch[i] = NULL;
648 ret = -EINVAL;
649 goto err_ch_mem;
650 }
651
Laxminath Kasamd1f36192017-08-03 18:54:01 +0530652 mutex_init(&ch[i]->mutex);
653 ch[i]->wpriv = wpriv;
654 INIT_WORK(&ch[i]->lcl_ch_open_wrk, wdsp_glink_lcl_ch_open_wrk);
655 INIT_WORK(&ch[i]->lcl_ch_cls_wrk, wdsp_glink_lcl_ch_cls_wrk);
656 init_waitqueue_head(&ch[i]->ch_connect_wait);
657 }
658
659 INIT_WORK(&wpriv->ch_open_cls_wrk, wdsp_glink_ch_open_cls_wrk);
660
661 /* Register glink link_state notification */
662 link_info.glink_link_state_notif_cb = wdsp_glink_link_state_cb;
663 link_info.transport = NULL;
664 link_info.edge = WDSP_EDGE;
665
666 wpriv->glink_state.link_state = GLINK_LINK_STATE_DOWN;
667 wpriv->glink_state.handle = glink_register_link_state_cb(&link_info,
668 wpriv);
669 if (!wpriv->glink_state.handle) {
670 dev_err(wpriv->dev, "%s: Unable to register wdsp link state\n",
671 __func__);
672 ret = -EINVAL;
673 goto err_ch_mem;
674 }
675 goto done;
676
677err_ch_mem:
678 for (j = 0; j < i; j++) {
679 mutex_destroy(&ch[j]->mutex);
680 kfree(wpriv->ch[j]);
681 wpriv->ch[j] = NULL;
682 }
683 kfree(wpriv->ch);
684 wpriv->ch = NULL;
685 wpriv->no_of_channels = 0;
686
687done:
688 mutex_unlock(&wpriv->glink_mutex);
689 return ret;
690}
691
692/*
693 * wdsp_glink_tx_buf_work - Work queue function to send tx buffer to glink
694 * work: Work structure
695 */
696static void wdsp_glink_tx_buf_work(struct work_struct *work)
697{
698 struct wdsp_glink_priv *wpriv;
699 struct wdsp_glink_ch *ch;
700 struct wdsp_glink_tx_buf *tx_buf;
701 struct wdsp_write_pkt *wpkt;
702 struct wdsp_cmd_pkt *cpkt;
703 int ret = 0;
704
705 tx_buf = container_of(work, struct wdsp_glink_tx_buf,
706 tx_work);
707 ch = tx_buf->ch;
708 wpriv = ch->wpriv;
709 wpkt = (struct wdsp_write_pkt *)tx_buf->buf;
710 cpkt = (struct wdsp_cmd_pkt *)wpkt->payload;
711 dev_dbg(wpriv->dev, "%s: ch name = %s, payload size = %d\n",
712 __func__, cpkt->ch_name, cpkt->payload_size);
713
714 mutex_lock(&tx_buf->ch->mutex);
715 if (ch->channel_state == GLINK_CONNECTED) {
716 mutex_unlock(&tx_buf->ch->mutex);
717 ret = glink_tx(ch->handle, tx_buf,
718 cpkt->payload, cpkt->payload_size,
719 GLINK_TX_REQ_INTENT);
720 if (ret < 0) {
721 dev_err(wpriv->dev, "%s: glink tx failed, ret = %d\n",
722 __func__, ret);
723 /*
724 * If glink_tx() is failed then free tx_buf here as
725 * there won't be any tx_done notification to
726 * free the buffer.
727 */
728 vfree(tx_buf);
729 }
730 } else {
731 mutex_unlock(&tx_buf->ch->mutex);
732 dev_err(wpriv->dev, "%s: channel %s is not in connected state\n",
733 __func__, ch->ch_cfg.name);
734 /*
735 * Free tx_buf here as there won't be any tx_done
736 * notification in this case also.
737 */
738 vfree(tx_buf);
739 }
740}
741
742/*
743 * wdsp_glink_read - Read API to send the data to userspace
744 * file: Pointer to the file structure
745 * buf: Pointer to the userspace buffer
746 * count: Number bytes to read from the file
747 * ppos: Pointer to the position into the file
748 */
749static ssize_t wdsp_glink_read(struct file *file, char __user *buf,
750 size_t count, loff_t *ppos)
751{
752 int ret = 0, ret1 = 0;
753 struct wdsp_glink_rsp_que *rsp;
754 struct wdsp_glink_priv *wpriv;
755
756 wpriv = (struct wdsp_glink_priv *)file->private_data;
757 if (!wpriv) {
758 pr_err("%s: Invalid private data\n", __func__);
759 ret = -EINVAL;
760 goto done;
761 }
762
763 if (count > WDSP_MAX_READ_SIZE) {
Vidyakumar Athota60871bd2017-09-08 11:26:51 -0700764 dev_info_ratelimited(wpriv->dev, "%s: count = %zd is more than WDSP_MAX_READ_SIZE\n",
Laxminath Kasamd1f36192017-08-03 18:54:01 +0530765 __func__, count);
766 count = WDSP_MAX_READ_SIZE;
767 }
768 /*
769 * Complete signal has given from glink rx notification callback
770 * or from flush API. Also use interruptible wait_for_completion API
771 * to allow the system to go in suspend.
772 */
773 ret = wait_for_completion_interruptible(&wpriv->rsp_complete);
774 if (ret)
775 goto done;
776
777 mutex_lock(&wpriv->rsp_mutex);
778 if (wpriv->rsp_cnt) {
779 wpriv->rsp_cnt--;
780 dev_dbg(wpriv->dev, "%s: read from buffer %d\n",
781 __func__, wpriv->rsp_cnt);
782
783 rsp = &wpriv->rsp[wpriv->rsp_cnt];
784 if (count < rsp->buf_size) {
785 ret1 = copy_to_user(buf, &rsp->buf, count);
786 /* Return the number of bytes copied */
787 ret = count;
788 } else {
789 ret1 = copy_to_user(buf, &rsp->buf, rsp->buf_size);
790 /* Return the number of bytes copied */
791 ret = rsp->buf_size;
792 }
793
794 if (ret1) {
795 mutex_unlock(&wpriv->rsp_mutex);
Vidyakumar Athota60871bd2017-09-08 11:26:51 -0700796 dev_err_ratelimited(wpriv->dev, "%s: copy_to_user failed %d\n",
Laxminath Kasamd1f36192017-08-03 18:54:01 +0530797 __func__, ret);
798 ret = -EFAULT;
799 goto done;
800 }
801 } else {
802 /*
803 * This will execute only if flush API is called or
804 * something wrong with ref_cnt
805 */
806 dev_dbg(wpriv->dev, "%s: resp count = %d\n", __func__,
807 wpriv->rsp_cnt);
808 ret = -EINVAL;
809 }
810 mutex_unlock(&wpriv->rsp_mutex);
811
812done:
813 return ret;
814}
815
816/*
817 * wdsp_glink_write - Write API to receive the data from userspace
818 * file: Pointer to the file structure
819 * buf: Pointer to the userspace buffer
820 * count: Number bytes to read from the file
821 * ppos: Pointer to the position into the file
822 */
823static ssize_t wdsp_glink_write(struct file *file, const char __user *buf,
824 size_t count, loff_t *ppos)
825{
826 int ret = 0, i, tx_buf_size;
827 struct wdsp_write_pkt *wpkt;
828 struct wdsp_cmd_pkt *cpkt;
829 struct wdsp_glink_tx_buf *tx_buf;
830 struct wdsp_glink_priv *wpriv;
831 size_t pkt_max_size;
832
833 wpriv = (struct wdsp_glink_priv *)file->private_data;
834 if (!wpriv) {
835 pr_err("%s: Invalid private data\n", __func__);
836 ret = -EINVAL;
837 goto done;
838 }
839
840 if ((count < WDSP_WRITE_PKT_SIZE) ||
841 (count > WDSP_MAX_WRITE_SIZE)) {
Vidyakumar Athota60871bd2017-09-08 11:26:51 -0700842 dev_err_ratelimited(wpriv->dev, "%s: Invalid count = %zd\n",
Laxminath Kasamd1f36192017-08-03 18:54:01 +0530843 __func__, count);
844 ret = -EINVAL;
845 goto done;
846 }
847
848 dev_dbg(wpriv->dev, "%s: count = %zd\n", __func__, count);
849
850 tx_buf_size = count + sizeof(struct wdsp_glink_tx_buf);
851 tx_buf = vzalloc(tx_buf_size);
852 if (!tx_buf) {
853 ret = -ENOMEM;
854 goto done;
855 }
856
857 ret = copy_from_user(tx_buf->buf, buf, count);
858 if (ret) {
Vidyakumar Athota60871bd2017-09-08 11:26:51 -0700859 dev_err_ratelimited(wpriv->dev, "%s: copy_from_user failed %d\n",
Laxminath Kasamd1f36192017-08-03 18:54:01 +0530860 __func__, ret);
861 ret = -EFAULT;
862 goto free_buf;
863 }
864
865 wpkt = (struct wdsp_write_pkt *)tx_buf->buf;
866 switch (wpkt->pkt_type) {
867 case WDSP_REG_PKT:
868 if (count < (WDSP_WRITE_PKT_SIZE + WDSP_REG_PKT_SIZE +
869 WDSP_CH_CFG_SIZE)) {
Vidyakumar Athota60871bd2017-09-08 11:26:51 -0700870 dev_err_ratelimited(wpriv->dev, "%s: Invalid reg pkt size = %zd\n",
Laxminath Kasamd1f36192017-08-03 18:54:01 +0530871 __func__, count);
872 ret = -EINVAL;
873 goto free_buf;
874 }
875 ret = wdsp_glink_ch_info_init(wpriv,
876 (struct wdsp_reg_pkt *)wpkt->payload,
877 count);
878 if (ret < 0)
Vidyakumar Athota60871bd2017-09-08 11:26:51 -0700879 dev_err_ratelimited(wpriv->dev, "%s: glink register failed, ret = %d\n",
Laxminath Kasamd1f36192017-08-03 18:54:01 +0530880 __func__, ret);
881 vfree(tx_buf);
882 break;
883 case WDSP_READY_PKT:
884 ret = wait_event_timeout(wpriv->link_state_wait,
885 (wpriv->glink_state.link_state ==
886 GLINK_LINK_STATE_UP),
887 msecs_to_jiffies(TIMEOUT_MS));
888 if (!ret) {
Vidyakumar Athota60871bd2017-09-08 11:26:51 -0700889 dev_err_ratelimited(wpriv->dev, "%s: Link state wait timeout\n",
Laxminath Kasamd1f36192017-08-03 18:54:01 +0530890 __func__);
891 ret = -ETIMEDOUT;
892 goto free_buf;
893 }
894 ret = 0;
895 vfree(tx_buf);
896 break;
897 case WDSP_CMD_PKT:
898 if (count <= (WDSP_WRITE_PKT_SIZE + WDSP_CMD_PKT_SIZE)) {
Vidyakumar Athota60871bd2017-09-08 11:26:51 -0700899 dev_err_ratelimited(wpriv->dev, "%s: Invalid cmd pkt size = %zd\n",
Laxminath Kasamd1f36192017-08-03 18:54:01 +0530900 __func__, count);
901 ret = -EINVAL;
902 goto free_buf;
903 }
904 mutex_lock(&wpriv->glink_mutex);
905 if (wpriv->glink_state.link_state == GLINK_LINK_STATE_DOWN) {
906 mutex_unlock(&wpriv->glink_mutex);
Vidyakumar Athota60871bd2017-09-08 11:26:51 -0700907 dev_err_ratelimited(wpriv->dev, "%s: Link state is Down\n",
Laxminath Kasamd1f36192017-08-03 18:54:01 +0530908 __func__);
909
910 ret = -ENETRESET;
911 goto free_buf;
912 }
913 mutex_unlock(&wpriv->glink_mutex);
914 cpkt = (struct wdsp_cmd_pkt *)wpkt->payload;
915 pkt_max_size = sizeof(struct wdsp_write_pkt) +
916 sizeof(struct wdsp_cmd_pkt) +
917 cpkt->payload_size;
918 if (count < pkt_max_size) {
Vidyakumar Athota60871bd2017-09-08 11:26:51 -0700919 dev_err_ratelimited(wpriv->dev, "%s: Invalid cmd pkt count = %zd, pkt_size = %zd\n",
Laxminath Kasamd1f36192017-08-03 18:54:01 +0530920 __func__, count, pkt_max_size);
921 ret = -EINVAL;
922 goto free_buf;
923 }
Laxminath Kasamd1f36192017-08-03 18:54:01 +0530924 for (i = 0; i < wpriv->no_of_channels; i++) {
925 if (wpriv->ch && wpriv->ch[i] &&
926 (!strcmp(cpkt->ch_name,
927 wpriv->ch[i]->ch_cfg.name))) {
928 tx_buf->ch = wpriv->ch[i];
929 break;
930 }
931 }
932 if (!tx_buf->ch) {
Vidyakumar Athota60871bd2017-09-08 11:26:51 -0700933 dev_err_ratelimited(wpriv->dev, "%s: Failed to get glink channel\n",
Laxminath Kasamd1f36192017-08-03 18:54:01 +0530934 __func__);
935 ret = -EINVAL;
936 goto free_buf;
937 }
Vidyakumar Athota87c83b72017-09-19 12:06:46 -0700938 dev_dbg(wpriv->dev, "%s: requested ch_name: %s, pkt_size: %zd\n",
939 __func__, cpkt->ch_name, pkt_max_size);
Laxminath Kasamd1f36192017-08-03 18:54:01 +0530940
941 ret = wait_event_timeout(tx_buf->ch->ch_connect_wait,
942 (tx_buf->ch->channel_state ==
943 GLINK_CONNECTED),
944 msecs_to_jiffies(TIMEOUT_MS));
945 if (!ret) {
Vidyakumar Athota60871bd2017-09-08 11:26:51 -0700946 dev_err_ratelimited(wpriv->dev, "%s: glink channel %s is not in connected state %d\n",
Laxminath Kasamd1f36192017-08-03 18:54:01 +0530947 __func__, tx_buf->ch->ch_cfg.name,
948 tx_buf->ch->channel_state);
949 ret = -ETIMEDOUT;
950 goto free_buf;
951 }
952 ret = 0;
953
954 INIT_WORK(&tx_buf->tx_work, wdsp_glink_tx_buf_work);
955 queue_work(wpriv->work_queue, &tx_buf->tx_work);
956 break;
957 default:
Vidyakumar Athota60871bd2017-09-08 11:26:51 -0700958 dev_err_ratelimited(wpriv->dev, "%s: Invalid packet type\n",
959 __func__);
Laxminath Kasamd1f36192017-08-03 18:54:01 +0530960 ret = -EINVAL;
961 vfree(tx_buf);
962 break;
963 }
964 goto done;
965
966free_buf:
967 vfree(tx_buf);
968
969done:
970 return ret;
971}
972
973/*
974 * wdsp_glink_open - Open API to initialize private data
975 * inode: Pointer to the inode structure
976 * file: Pointer to the file structure
977 */
978static int wdsp_glink_open(struct inode *inode, struct file *file)
979{
980 int ret = 0;
981 struct wdsp_glink_priv *wpriv;
982 struct wdsp_glink_dev *wdev;
983
984 if (!inode->i_cdev) {
985 pr_err("%s: cdev is NULL\n", __func__);
986 ret = -EINVAL;
987 goto done;
988 }
989 wdev = container_of(inode->i_cdev, struct wdsp_glink_dev, cdev);
990
991 wpriv = kzalloc(sizeof(struct wdsp_glink_priv), GFP_KERNEL);
992 if (!wpriv) {
993 ret = -ENOMEM;
994 goto done;
995 }
996 wpriv->dev = wdev->dev;
997 wpriv->work_queue = create_singlethread_workqueue("wdsp_glink_wq");
998 if (!wpriv->work_queue) {
999 dev_err(wpriv->dev, "%s: Error creating wdsp_glink_wq\n",
1000 __func__);
1001 ret = -EINVAL;
1002 goto err_wq;
1003 }
1004
Vidyakumar Athota60871bd2017-09-08 11:26:51 -07001005 wpriv->glink_state.link_state = GLINK_LINK_STATE_DOWN;
Laxminath Kasamd1f36192017-08-03 18:54:01 +05301006 init_completion(&wpriv->rsp_complete);
1007 init_waitqueue_head(&wpriv->link_state_wait);
1008 mutex_init(&wpriv->rsp_mutex);
1009 mutex_init(&wpriv->glink_mutex);
1010 file->private_data = wpriv;
1011
1012 goto done;
1013
1014err_wq:
1015 kfree(wpriv);
1016
1017done:
1018 return ret;
1019}
1020
1021/*
1022 * wdsp_glink_flush - Flush API to unblock read.
1023 * file: Pointer to the file structure
1024 * id: Lock owner ID
1025 */
1026static int wdsp_glink_flush(struct file *file, fl_owner_t id)
1027{
1028 struct wdsp_glink_priv *wpriv;
1029
1030 wpriv = (struct wdsp_glink_priv *)file->private_data;
1031 if (!wpriv) {
1032 pr_err("%s: Invalid private data\n", __func__);
1033 return -EINVAL;
1034 }
1035
1036 complete(&wpriv->rsp_complete);
1037
1038 return 0;
1039}
1040
1041/*
1042 * wdsp_glink_release - Release API to clean up resources.
1043 * Whenever a file structure is shared across multiple threads,
1044 * release won't be invoked until all copies are closed
1045 * (file->f_count.counter should be 0). If we need to flush pending
1046 * data when any copy is closed, you should implement the flush method.
1047 *
1048 * inode: Pointer to the inode structure
1049 * file: Pointer to the file structure
1050 */
1051static int wdsp_glink_release(struct inode *inode, struct file *file)
1052{
1053 int i, ret = 0;
1054 struct wdsp_glink_priv *wpriv;
1055
1056 wpriv = (struct wdsp_glink_priv *)file->private_data;
1057 if (!wpriv) {
1058 pr_err("%s: Invalid private data\n", __func__);
1059 ret = -EINVAL;
1060 goto done;
1061 }
1062
1063 if (wpriv->glink_state.handle)
1064 glink_unregister_link_state_cb(wpriv->glink_state.handle);
1065
1066 flush_workqueue(wpriv->work_queue);
1067 destroy_workqueue(wpriv->work_queue);
1068
1069 /*
1070 * Clean up glink channel memory in channel state
1071 * callback only if close channels are called from here.
1072 */
1073 if (wpriv->ch) {
1074 for (i = 0; i < wpriv->no_of_channels; i++) {
1075 if (wpriv->ch[i]) {
1076 wpriv->ch[i]->free_mem = true;
1077 /*
1078 * Channel handle NULL means channel is already
1079 * closed. Free the channel memory here itself.
1080 */
1081 if (!wpriv->ch[i]->handle) {
1082 kfree(wpriv->ch[i]);
1083 wpriv->ch[i] = NULL;
1084 } else {
1085 wdsp_glink_close_ch(wpriv->ch[i]);
1086 }
1087 }
1088 }
1089
1090 kfree(wpriv->ch);
1091 wpriv->ch = NULL;
1092 }
1093
1094 mutex_destroy(&wpriv->glink_mutex);
1095 mutex_destroy(&wpriv->rsp_mutex);
1096 kfree(wpriv);
1097 file->private_data = NULL;
1098
1099done:
1100 return ret;
1101}
1102
1103static const struct file_operations wdsp_glink_fops = {
1104 .owner = THIS_MODULE,
1105 .open = wdsp_glink_open,
1106 .read = wdsp_glink_read,
1107 .write = wdsp_glink_write,
1108 .flush = wdsp_glink_flush,
1109 .release = wdsp_glink_release,
1110};
1111
1112/*
1113 * wdsp_glink_probe - Driver probe to expose char device
1114 * pdev: Pointer to device tree data.
1115 */
1116static int wdsp_glink_probe(struct platform_device *pdev)
1117{
1118 int ret;
1119 struct wdsp_glink_dev *wdev;
1120
1121 wdev = devm_kzalloc(&pdev->dev, sizeof(*wdev), GFP_KERNEL);
1122 if (!wdev) {
1123 ret = -ENOMEM;
1124 goto done;
1125 }
1126
1127 ret = alloc_chrdev_region(&wdev->dev_num, 0, MINOR_NUMBER_COUNT,
1128 WDSP_GLINK_DRIVER_NAME);
1129 if (ret < 0) {
1130 dev_err(&pdev->dev, "%s: Failed to alloc char dev, err = %d\n",
1131 __func__, ret);
1132 goto err_chrdev;
1133 }
1134
1135 wdev->cls = class_create(THIS_MODULE, WDSP_GLINK_DRIVER_NAME);
1136 if (IS_ERR(wdev->cls)) {
1137 ret = PTR_ERR(wdev->cls);
1138 dev_err(&pdev->dev, "%s: Failed to create class, err = %d\n",
1139 __func__, ret);
1140 goto err_class;
1141 }
1142
1143 wdev->dev = device_create(wdev->cls, NULL, wdev->dev_num,
1144 NULL, WDSP_GLINK_DRIVER_NAME);
1145 if (IS_ERR(wdev->dev)) {
1146 ret = PTR_ERR(wdev->dev);
1147 dev_err(&pdev->dev, "%s: Failed to create device, err = %d\n",
1148 __func__, ret);
1149 goto err_dev_create;
1150 }
1151
1152 cdev_init(&wdev->cdev, &wdsp_glink_fops);
1153 ret = cdev_add(&wdev->cdev, wdev->dev_num, MINOR_NUMBER_COUNT);
1154 if (ret < 0) {
1155 dev_err(&pdev->dev, "%s: Failed to register char dev, err = %d\n",
1156 __func__, ret);
1157 goto err_cdev_add;
1158 }
1159 platform_set_drvdata(pdev, wdev);
1160 goto done;
1161
1162err_cdev_add:
1163 device_destroy(wdev->cls, wdev->dev_num);
1164
1165err_dev_create:
1166 class_destroy(wdev->cls);
1167
1168err_class:
1169 unregister_chrdev_region(0, MINOR_NUMBER_COUNT);
1170
1171err_chrdev:
1172 devm_kfree(&pdev->dev, wdev);
1173
1174done:
1175 return ret;
1176}
1177
1178/*
1179 * wdsp_glink_remove - Driver remove to handle cleanup
1180 * pdev: Pointer to device tree data.
1181 */
1182static int wdsp_glink_remove(struct platform_device *pdev)
1183{
1184 struct wdsp_glink_dev *wdev = platform_get_drvdata(pdev);
1185
1186 if (wdev) {
1187 cdev_del(&wdev->cdev);
1188 device_destroy(wdev->cls, wdev->dev_num);
1189 class_destroy(wdev->cls);
1190 unregister_chrdev_region(0, MINOR_NUMBER_COUNT);
1191 devm_kfree(&pdev->dev, wdev);
1192 } else {
1193 dev_err(&pdev->dev, "%s: Invalid device data\n", __func__);
1194 }
1195
1196 return 0;
1197}
1198
1199static const struct of_device_id wdsp_glink_of_match[] = {
1200 {.compatible = "qcom,wcd-dsp-glink"},
1201 { }
1202};
1203MODULE_DEVICE_TABLE(of, wdsp_glink_of_match);
1204
1205static struct platform_driver wdsp_glink_driver = {
1206 .probe = wdsp_glink_probe,
1207 .remove = wdsp_glink_remove,
1208 .driver = {
1209 .name = WDSP_GLINK_DRIVER_NAME,
1210 .owner = THIS_MODULE,
1211 .of_match_table = wdsp_glink_of_match,
1212 },
1213};
1214
1215module_platform_driver(wdsp_glink_driver);
1216
1217MODULE_DESCRIPTION("SoC WCD_DSP GLINK Driver");
1218MODULE_LICENSE("GPL v2");