blob: 4288608e63557e0daf1ce570462a52e41eabda7e [file] [log] [blame]
Sundara Vinayagama2356d22018-05-21 13:39:39 +05301/* Copyright (c) 2017-2018, 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#include <linux/kernel.h>
13#include <linux/module.h>
14#include <linux/types.h>
15#include <linux/slab.h>
16#include <linux/uaccess.h>
17#include <linux/of.h>
18#include <linux/mutex.h>
19#include <soc/bg_glink.h>
20#include <linux/wait.h>
21#include <linux/errno.h>
22#include <linux/debugfs.h>
23#include <linux/platform_device.h>
24#include <linux/delay.h>
25#include <soc/qcom/glink.h>
26
27#define GLINK_LINK_STATE_UP_WAIT_TIMEOUT 5000
28#define APR_MAXIMUM_NUM_OF_RETRIES 2
29#define BG_RX_INTENT_REQ_TIMEOUT_MS 3000
30#define BG_GLINK_NAME "bg-cdc-glink"
31#define BG_GLINK_EDGE "bg"
32#define BG_MAX_NO_OF_INTENTS 20
33
34struct bg_cdc_glink_drvdata {
35 struct device *dev;
36 struct platform_device *pdev;
37 struct bg_cdc_glink_ch_info *ch_info;
38 void *handle;
39 wait_queue_head_t wait;
40 u8 num_channels;
41 u8 active_channel;
42 enum glink_link_state link_state;
43};
44
45struct bg_cdc_glink_ch_info {
46 void *handle;
47 struct mutex w_lock;
48 struct mutex r_lock;
49 struct mutex m_lock;
50 bg_glink_cb_fn func;
51 wait_queue_head_t wait;
52 unsigned channel_state;
53 bool if_remote_intent_ready;
54};
55static int __bg_cdc_glink_write(struct bg_cdc_glink_ch_info *ch_info,
56 void *data, char *tx_buf, int len)
57{
58 int rc = 0;
59
60 if (!ch_info)
61 return -EINVAL;
62 mutex_lock(&ch_info->w_lock);
63 rc = glink_tx(ch_info->handle, tx_buf, data, len, GLINK_TX_REQ_INTENT);
64 mutex_unlock(&ch_info->w_lock);
65
66 if (rc)
67 pr_err("%s: glink_tx failed, rc[%d]\n", __func__, rc);
68 else
69 rc = len;
70
71 return rc;
72}
73
74int bg_cdc_glink_write(void *ch_info, void *data,
75 int len)
76{
77 int rc = 0;
78 char *tx_buf = NULL;
79
80 if (!((struct bg_cdc_glink_ch_info *)ch_info)->handle || !data)
81 return -EINVAL;
82
83 /* check if channel is connected before proceeding */
84 if (((struct bg_cdc_glink_ch_info *)ch_info)->channel_state
85 != GLINK_CONNECTED) {
86 pr_err("%s: channel is not connected\n", __func__);
87 return -EINVAL;
88 }
89
90 tx_buf = kzalloc((sizeof(char) * len), GFP_KERNEL);
91 if (IS_ERR_OR_NULL(tx_buf)) {
92 rc = -EINVAL;
93 goto exit;
94 }
95 memcpy(tx_buf, data, len);
96
97 rc = __bg_cdc_glink_write((struct bg_cdc_glink_ch_info *)ch_info,
98 tx_buf, tx_buf, len);
99
100 if (rc < 0) {
101 pr_err("%s: Unable to send the packet, rc:%d\n", __func__, rc);
102 kfree(tx_buf);
103 }
104exit:
105 return rc;
106}
107EXPORT_SYMBOL(bg_cdc_glink_write);
108
109static void bg_cdc_glink_notify_rx(void *handle, const void *priv,
110 const void *pkt_priv, const void *ptr,
111 size_t size)
112{
113 struct bg_cdc_glink_ch_info *ch_info =
114 (struct bg_cdc_glink_ch_info *)priv;
115
116 if (!ch_info || !ptr) {
117 pr_err("%s: Invalid ch_info or ptr\n", __func__);
118 return;
119 }
120
121 pr_debug("%s: Rx packet received\n", __func__);
122
123 mutex_lock(&ch_info->r_lock);
124 if (ch_info->func)
125 ch_info->func((void *)ptr, size);
126 mutex_unlock(&ch_info->r_lock);
127 glink_rx_done(ch_info->handle, ptr, true);
128}
129
130static void bg_cdc_glink_notify_tx_abort(void *handle, const void *priv,
131 const void *pkt_priv)
132{
133 pr_debug("%s: tx_abort received for pkt_priv:%pK\n",
134 __func__, pkt_priv);
135 kfree(pkt_priv);
136}
137
138static void bg_cdc_glink_notify_tx_done(void *handle, const void *priv,
139 const void *pkt_priv, const void *ptr)
140{
141 pr_debug("%s: tx_done received for pkt_priv:%pK\n",
142 __func__, pkt_priv);
143 kfree(pkt_priv);
144}
145
146static bool bg_cdc_glink_notify_rx_intent_req(void *handle, const void *priv,
147 size_t req_size)
148{
149 struct bg_cdc_glink_ch_info *ch_info =
150 (struct bg_cdc_glink_ch_info *)priv;
151
152 if (!ch_info) {
153 pr_err("%s: Invalid ch_info\n", __func__);
154 return false;
155 }
156
157 pr_debug("%s: No rx intents queued, unable to receive\n", __func__);
158 return false;
159}
160
161static void bg_cdc_glink_notify_remote_rx_intent(void *handle, const void *priv,
162 size_t size)
163{
164 struct bg_cdc_glink_ch_info *ch_info =
165 (struct bg_cdc_glink_ch_info *)priv;
166
167 if (!ch_info) {
168 pr_err("%s: Invalid ch_info\n", __func__);
169 return;
170 }
171 /*
172 * This is to make sure that the far end has queued at least one intent
173 * before we attempt any IPC.
174 */
175 pr_debug("%s: remote queued an intent\n", __func__);
176 ch_info->if_remote_intent_ready = true;
177 wake_up(&ch_info->wait);
178}
179
180static void bg_cdc_glink_notify_state(void *handle, const void *priv,
181 unsigned event)
182{
183 struct bg_cdc_glink_ch_info *ch_info =
184 (struct bg_cdc_glink_ch_info *)priv;
185
186 if (!ch_info) {
187 pr_err("%s: Invalid ch_info\n", __func__);
188 return;
189 }
190
191 ch_info->channel_state = event;
192 pr_debug("%s: Channel state[%d]\n", __func__, event);
193
194 if (event == GLINK_CONNECTED)
195 wake_up(&ch_info->wait);
196}
197
198static int bg_cdc_glink_rx_intents_config(struct bg_cdc_glink_ch_info *ch_info,
199 int num_of_intents, uint32_t *size)
200{
201 int i;
202 int rc = 0;
203
204 if (!ch_info || !num_of_intents || !size) {
205 pr_err("%s: Invalid parameter\n", __func__);
206 return -EINVAL;
207 }
208 if (num_of_intents > BG_MAX_NO_OF_INTENTS) {
209 pr_err("%s: Invalid no_of_intents = %d\n",
210 __func__, num_of_intents);
211 return -EINVAL;
212 }
213
214 for (i = 0; i < num_of_intents; i++) {
215 rc = glink_queue_rx_intent(ch_info->handle, ch_info, *(size+i));
216 if (rc) {
217 pr_err("%s: Failed to queue rx intent, iteration[%d]\n",
218 __func__, i);
219 break;
220 }
221 }
222
223 return rc;
224}
225/*
226 * bg_cdc_channel_open - API to open Glink channel.
227 * ch_cfg: glink channel configuration
228 * func: callback function to notify client.
229 */
230void *bg_cdc_channel_open(struct platform_device *pdev,
231 struct bg_glink_ch_cfg *ch_cfg,
232 bg_glink_cb_fn func)
233{
234 int rc;
235 struct bg_cdc_glink_drvdata *bg_cdc_glink;
236 struct glink_open_config open_cfg;
237 struct bg_cdc_glink_ch_info *ch_info;
238
239 if (!pdev) {
240 pr_err("%s: invalid platform device\n",__func__);
241 return NULL;
242 }
243 bg_cdc_glink = platform_get_drvdata(pdev);
244
245 if (!bg_cdc_glink) {
246 dev_err(&pdev->dev, "%s: driver data not found\n",
247 __func__);
248 return NULL;
249 }
250 if (bg_cdc_glink->active_channel > bg_cdc_glink->num_channels) {
251 dev_err(bg_cdc_glink->dev, "%s: invalid channel number\n",
252 __func__);
253 return NULL;
254 }
255
256 ch_info = &bg_cdc_glink->ch_info[bg_cdc_glink->active_channel];
257 mutex_lock(&ch_info->m_lock);
258 if (ch_info->handle) {
259 dev_err(&pdev->dev, "%s: This channel is already opened\n",
260 __func__);
261 rc = -EBUSY;
262 goto unlock;
263 }
264
265 if (bg_cdc_glink->link_state != GLINK_LINK_STATE_UP) {
266 rc = wait_event_timeout(bg_cdc_glink->wait,
267 bg_cdc_glink->link_state == GLINK_LINK_STATE_UP,
268 msecs_to_jiffies(GLINK_LINK_STATE_UP_WAIT_TIMEOUT));
269 if (rc == 0) {
270 dev_err(bg_cdc_glink->dev, "%s: Open timeout\n",
271 __func__);
272 rc = -ETIMEDOUT;
273 goto unlock;
274 }
275 dev_dbg(bg_cdc_glink->dev, "%s: Wakeup done\n", __func__);
276 }
277
278 memset(&open_cfg, 0, sizeof(struct glink_open_config));
279 open_cfg.options = GLINK_OPT_INITIAL_XPORT;
280 open_cfg.edge = BG_GLINK_EDGE;
281 open_cfg.name = ch_cfg->ch_name;
282 open_cfg.notify_rx = bg_cdc_glink_notify_rx;
283 open_cfg.notify_tx_done = bg_cdc_glink_notify_tx_done;
284 open_cfg.notify_state = bg_cdc_glink_notify_state;
285 open_cfg.notify_rx_intent_req = bg_cdc_glink_notify_rx_intent_req;
286 open_cfg.notify_remote_rx_intent = bg_cdc_glink_notify_remote_rx_intent;
287 open_cfg.notify_tx_abort = bg_cdc_glink_notify_tx_abort;
288 open_cfg.rx_intent_req_timeout_ms = BG_RX_INTENT_REQ_TIMEOUT_MS;
289 open_cfg.priv = ch_info;
290
291 ch_info->channel_state = GLINK_REMOTE_DISCONNECTED;
292 ch_info->handle = glink_open(&open_cfg);
293 if (IS_ERR_OR_NULL(ch_info->handle)) {
294 dev_err(bg_cdc_glink->dev, "%s: glink_open failed %s\n",
295 __func__, ch_cfg->ch_name);
296 ch_info->handle = NULL;
297 rc = -EINVAL;
298 goto unlock;
299 }
300 bg_cdc_glink->active_channel++;
301 rc = wait_event_timeout(ch_info->wait,
302 (ch_info->channel_state == GLINK_CONNECTED), 5 * HZ);
303 if (rc == 0) {
304 dev_err(bg_cdc_glink->dev, "%s: TIMEOUT for OPEN event\n",
305 __func__);
306 rc = -ETIMEDOUT;
307 goto close_link;
308 }
309 rc = bg_cdc_glink_rx_intents_config(ch_info,
310 ch_cfg->num_of_intents, ch_cfg->intents_size);
311 if (rc) {
312 dev_err(bg_cdc_glink->dev, "%s: Unable to queue intents\n",
313 __func__);
314 goto close_link;
315 }
316
317 ch_info->func = func;
318
319close_link:
320 if (rc) {
321 if (bg_cdc_glink->active_channel > 0)
322 bg_cdc_glink->active_channel--;
323 glink_close(ch_info->handle);
324 ch_info->handle = NULL;
325 }
326unlock:
327 mutex_unlock(&ch_info->m_lock);
328
329 return rc ? NULL : (void *)ch_info;
330}
331EXPORT_SYMBOL(bg_cdc_channel_open);
332
333
334int bg_cdc_channel_close(struct platform_device *pdev,
335 void *ch_info)
336{
337 struct bg_cdc_glink_drvdata *bg_cdc_glink;
338 int rc;
339 struct bg_cdc_glink_ch_info *channel_info
340 = (struct bg_cdc_glink_ch_info *)ch_info;
341 bg_cdc_glink = platform_get_drvdata(pdev);
342 if (!channel_info || !channel_info->handle) {
343 rc = -EINVAL;
344 goto exit;
345 }
346
347 mutex_lock(&channel_info->m_lock);
348 if (bg_cdc_glink->active_channel > 0)
349 bg_cdc_glink->active_channel--;
350 rc = glink_close(channel_info->handle);
351 channel_info->handle = NULL;
352 channel_info->func = NULL;
353 channel_info->if_remote_intent_ready = false;
354 mutex_unlock(&channel_info->m_lock);
355exit:
356 return rc;
357}
358EXPORT_SYMBOL(bg_cdc_channel_close);
359
360static void bg_cdc_glink_link_state_cb(struct glink_link_state_cb_info *cb_info,
361 void *priv)
362{
363 struct bg_cdc_glink_drvdata *bg_cdc_glink =
364 (struct bg_cdc_glink_drvdata *) priv;
365
366 if (!cb_info) {
367 pr_err("%s: Invalid cb_info\n", __func__);
368 return;
369 }
370
371 dev_dbg(bg_cdc_glink->dev, "%s: edge[%s] link state[%d]\n", __func__,
372 cb_info->edge, cb_info->link_state);
373
374 bg_cdc_glink->link_state = cb_info->link_state;
375 if (bg_cdc_glink->link_state == GLINK_LINK_STATE_UP)
376 wake_up(&bg_cdc_glink->wait);
377}
378
379static int bg_cdc_glink_probe(struct platform_device *pdev)
380{
381 struct bg_cdc_glink_drvdata *bg_cdc_glink;
382 struct glink_link_info link_info;
383 u32 num_channels;
384 int ret = 0;
385 int i;
386
387 ret = of_property_read_u32(pdev->dev.of_node, "qcom,msm-glink-channels",
388 &num_channels);
389
390 if (ret) {
391 dev_err(&pdev->dev, "%s: glink channels from DT file %s\n",
392 __func__, "qcom,msm-glink-channels");
393 return -EINVAL;
394 }
395
396 /* Allocate BG codec Glink structure */
397 bg_cdc_glink = kzalloc(sizeof(struct bg_cdc_glink_drvdata), GFP_KERNEL);
398 if (!bg_cdc_glink)
399 return -ENOMEM;
400
401 bg_cdc_glink->ch_info = kzalloc((sizeof(struct bg_cdc_glink_ch_info) *
402 num_channels), GFP_KERNEL);
403 if (!bg_cdc_glink->ch_info) {
404 ret = -ENOMEM;
405 goto err_memory_fail;
406 }
407 bg_cdc_glink->dev = &pdev->dev;
408 bg_cdc_glink->pdev = pdev;
409 bg_cdc_glink->num_channels = num_channels;
410 platform_set_drvdata(pdev, bg_cdc_glink);
411
412 init_waitqueue_head(&bg_cdc_glink->wait);
413
414 /* Register glink link_state notification */
415 link_info.glink_link_state_notif_cb = bg_cdc_glink_link_state_cb;
416 link_info.transport = NULL;
417 link_info.edge = BG_GLINK_EDGE;
418 bg_cdc_glink->link_state = GLINK_LINK_STATE_DOWN;
419 bg_cdc_glink->handle =
420 glink_register_link_state_cb(&link_info, bg_cdc_glink);
421 if (!bg_cdc_glink->handle) {
422 dev_err(&pdev->dev, "%s: Unable to register link state\n",
423 __func__);
424 ret = -EINVAL;
425 goto err_glink_register_fail;
426 }
427
428 for (i = 0; i < num_channels; i++) {
429 mutex_init(&bg_cdc_glink->ch_info[i].w_lock);
430 mutex_init(&bg_cdc_glink->ch_info[i].r_lock);
431 mutex_init(&bg_cdc_glink->ch_info[i].m_lock);
432 init_waitqueue_head(&bg_cdc_glink->ch_info[i].wait);
433 }
434 return ret;
435err_glink_register_fail:
436 kfree(bg_cdc_glink->ch_info);
437
438err_memory_fail:
439 kfree(bg_cdc_glink);
440
441 return ret;
442}
443
444static const struct of_device_id bg_cdc_glink_of_match[] = {
445 { .compatible = "qcom,bg-cdc-glink", },
446 {},
447};
448
449static int bg_cdc_glink_remove(struct platform_device *pdev)
450{
451 struct bg_cdc_glink_drvdata *bg_cdc_glink = platform_get_drvdata(pdev);
452 int i;
453
454 if (!bg_cdc_glink) {
455 dev_err(&pdev->dev, "%s: invalid data\n",
456 __func__);
457 return -EINVAL;
458 }
459 if (bg_cdc_glink->handle)
460 glink_unregister_link_state_cb(bg_cdc_glink->handle);
461
462 for (i = 0; i < bg_cdc_glink->num_channels; i++) {
463 mutex_destroy(&bg_cdc_glink->ch_info[i].w_lock);
464 mutex_destroy(&bg_cdc_glink->ch_info[i].r_lock);
465 mutex_destroy(&bg_cdc_glink->ch_info[i].m_lock);
466 }
467 kfree(bg_cdc_glink->ch_info);
468 kfree(bg_cdc_glink);
469 return 0;
470}
471
472static struct platform_driver msm_bg_cdc_glink_driver = {
473 .driver = {
474 .owner = THIS_MODULE,
475 .name = BG_GLINK_NAME,
476 .of_match_table = bg_cdc_glink_of_match,
477 },
478 .probe = bg_cdc_glink_probe,
479 .remove = bg_cdc_glink_remove,
480};
481module_platform_driver(msm_bg_cdc_glink_driver);
482
483MODULE_LICENSE("GPL v2");
484MODULE_DESCRIPTION("BG Glink driver");