blob: c93c1dae97b41dc671c2d2d83670fda5fb68473c [file] [log] [blame]
Arun Kumar Neelakantam011248b2018-03-09 14:57:51 +05301/* Copyright (c) 2008-2018, The Linux Foundation. All rights reserved.
Arun Kumar Neelakantamd680a242017-11-02 21:14:53 +05302 *
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/*
14 * SMD Packet Driver -- Provides a binary SMD non-muxed packet port
15 * interface.
16 */
17
18#include <linux/slab.h>
19#include <linux/cdev.h>
20#include <linux/module.h>
21#include <linux/fs.h>
22#include <linux/device.h>
23#include <linux/sched.h>
24#include <linux/spinlock.h>
25#include <linux/mutex.h>
26#include <linux/delay.h>
27#include <linux/uaccess.h>
28#include <linux/workqueue.h>
29#include <linux/platform_device.h>
30#include <linux/completion.h>
31#include <linux/msm_smd_pkt.h>
32#include <linux/poll.h>
33#include <soc/qcom/smd.h>
34#include <soc/qcom/smsm.h>
35#include <soc/qcom/subsystem_restart.h>
36#include <asm/ioctls.h>
37#include <linux/pm.h>
38#include <linux/of.h>
39#include <linux/ipc_logging.h>
40
41#define MODULE_NAME "msm_smdpkt"
42#define DEVICE_NAME "smdpkt"
43#define WAKEUPSOURCE_TIMEOUT (2000) /* two seconds */
44
45struct smd_pkt_dev {
46 struct list_head dev_list;
47 char dev_name[SMD_MAX_CH_NAME_LEN];
48 char ch_name[SMD_MAX_CH_NAME_LEN];
49 uint32_t edge;
50
51 struct cdev cdev;
52 struct device *devicep;
53 void *pil;
54
55 struct smd_channel *ch;
56 struct mutex ch_lock;
57 struct mutex rx_lock;
58 struct mutex tx_lock;
59 wait_queue_head_t ch_read_wait_queue;
60 wait_queue_head_t ch_write_wait_queue;
61 wait_queue_head_t ch_opened_wait_queue;
62
63 int i;
64 int ref_cnt;
65
66 int blocking_write;
67 int is_open;
68 int poll_mode;
69 unsigned int ch_size;
70 uint open_modem_wait;
71
72 int has_reset;
73 int do_reset_notification;
74 struct completion ch_allocated;
75 struct wakeup_source pa_ws; /* Packet Arrival Wakeup Source */
76 struct work_struct packet_arrival_work;
77 spinlock_t pa_spinlock;
78 int ws_locked;
Arun Kumar Neelakantam011248b2018-03-09 14:57:51 +053079
80 int sigs_updated;
Arun Kumar Neelakantamd680a242017-11-02 21:14:53 +053081};
82
83
84struct smd_pkt_driver {
85 struct list_head list;
86 int ref_cnt;
87 char pdriver_name[SMD_MAX_CH_NAME_LEN];
88 struct platform_driver driver;
89};
90
91static DEFINE_MUTEX(smd_pkt_driver_lock_lha1);
92static LIST_HEAD(smd_pkt_driver_list);
93
94struct class *smd_pkt_classp;
95static dev_t smd_pkt_number;
96static struct delayed_work loopback_work;
97static void check_and_wakeup_reader(struct smd_pkt_dev *smd_pkt_devp);
98static void check_and_wakeup_writer(struct smd_pkt_dev *smd_pkt_devp);
99static uint32_t is_modem_smsm_inited(void);
100
101static DEFINE_MUTEX(smd_pkt_dev_lock_lha1);
102static LIST_HEAD(smd_pkt_dev_list);
103static int num_smd_pkt_ports;
104
105#define SMD_PKT_IPC_LOG_PAGE_CNT 2
106static void *smd_pkt_ilctxt;
107
108static int msm_smd_pkt_debug_mask;
109module_param_named(debug_mask, msm_smd_pkt_debug_mask, int, 0664);
110
111enum {
112 SMD_PKT_STATUS = 1U << 0,
113 SMD_PKT_READ = 1U << 1,
114 SMD_PKT_WRITE = 1U << 2,
115 SMD_PKT_POLL = 1U << 5,
116};
117
118#define DEBUG
119
120#ifdef DEBUG
121
122#define SMD_PKT_LOG_STRING(x...) \
123do { \
124 if (smd_pkt_ilctxt) \
125 ipc_log_string(smd_pkt_ilctxt, "<SMD_PKT>: "x); \
126} while (0)
127
128#define D_STATUS(x...) \
129do { \
130 if (msm_smd_pkt_debug_mask & SMD_PKT_STATUS) \
131 pr_info("Status: "x); \
132 SMD_PKT_LOG_STRING(x); \
133} while (0)
134
135#define D_READ(x...) \
136do { \
137 if (msm_smd_pkt_debug_mask & SMD_PKT_READ) \
138 pr_info("Read: "x); \
139 SMD_PKT_LOG_STRING(x); \
140} while (0)
141
142#define D_WRITE(x...) \
143do { \
144 if (msm_smd_pkt_debug_mask & SMD_PKT_WRITE) \
145 pr_info("Write: "x); \
146 SMD_PKT_LOG_STRING(x); \
147} while (0)
148
149#define D_POLL(x...) \
150do { \
151 if (msm_smd_pkt_debug_mask & SMD_PKT_POLL) \
152 pr_info("Poll: "x); \
153 SMD_PKT_LOG_STRING(x); \
154} while (0)
155
156#define E_SMD_PKT_SSR(x) \
157do { \
158 if (x->do_reset_notification) \
159 pr_err("%s notifying reset for smd_pkt_dev id:%d\n", \
160 __func__, x->i); \
161} while (0)
162#else
163#define D_STATUS(x...) do {} while (0)
164#define D_READ(x...) do {} while (0)
165#define D_WRITE(x...) do {} while (0)
166#define D_POLL(x...) do {} while (0)
167#define E_SMD_PKT_SSR(x) do {} while (0)
168#endif
169
170static ssize_t open_timeout_store(struct device *d,
171 struct device_attribute *attr,
172 const char *buf,
173 size_t n)
174{
175 struct smd_pkt_dev *smd_pkt_devp;
176 unsigned long tmp;
177
178 mutex_lock(&smd_pkt_dev_lock_lha1);
179 list_for_each_entry(smd_pkt_devp, &smd_pkt_dev_list, dev_list) {
180 if (smd_pkt_devp->devicep == d) {
181 if (!kstrtoul(buf, 10, &tmp)) {
182 smd_pkt_devp->open_modem_wait = tmp;
183 mutex_unlock(&smd_pkt_dev_lock_lha1);
184 return n;
185 }
186 mutex_unlock(&smd_pkt_dev_lock_lha1);
187 pr_err("%s: unable to convert: %s to an int\n",
188 __func__, buf);
189 return -EINVAL;
190 }
191 }
192 mutex_unlock(&smd_pkt_dev_lock_lha1);
193
194 pr_err("%s: unable to match device to valid smd_pkt port\n", __func__);
195 return -EINVAL;
196}
197
198static ssize_t open_timeout_show(struct device *d,
199 struct device_attribute *attr,
200 char *buf)
201{
202 struct smd_pkt_dev *smd_pkt_devp;
203
204 mutex_lock(&smd_pkt_dev_lock_lha1);
205 list_for_each_entry(smd_pkt_devp, &smd_pkt_dev_list, dev_list) {
206 if (smd_pkt_devp->devicep == d) {
207 mutex_unlock(&smd_pkt_dev_lock_lha1);
208 return snprintf(buf, PAGE_SIZE, "%d\n",
209 smd_pkt_devp->open_modem_wait);
210 }
211 }
212 mutex_unlock(&smd_pkt_dev_lock_lha1);
213 pr_err("%s: unable to match device to valid smd_pkt port\n", __func__);
214 return -EINVAL;
215
216}
217
218static DEVICE_ATTR(open_timeout, 0664, open_timeout_show, open_timeout_store);
219
220/**
221 * loopback_edge_store() - Set the edge type for loopback device
222 * @d: Linux device structure
223 * @attr: Device attribute structure
224 * @buf: Input string
225 * @n: Length of the input string
226 *
227 * This function is used to set the loopback device edge runtime
228 * by writing to the loopback_edge node.
229 */
230static ssize_t loopback_edge_store(struct device *d,
231 struct device_attribute *attr,
232 const char *buf,
233 size_t n)
234{
235 struct smd_pkt_dev *smd_pkt_devp;
236 unsigned long tmp;
237
238 mutex_lock(&smd_pkt_dev_lock_lha1);
239 list_for_each_entry(smd_pkt_devp, &smd_pkt_dev_list, dev_list) {
240 if (smd_pkt_devp->devicep == d) {
241 if (!kstrtoul(buf, 10, &tmp)) {
242 smd_pkt_devp->edge = tmp;
243 mutex_unlock(&smd_pkt_dev_lock_lha1);
244 return n;
245 }
246 mutex_unlock(&smd_pkt_dev_lock_lha1);
247 pr_err("%s: unable to convert: %s to an int\n",
248 __func__, buf);
249 return -EINVAL;
250 }
251 }
252 mutex_unlock(&smd_pkt_dev_lock_lha1);
253 pr_err("%s: unable to match device to valid smd_pkt port\n", __func__);
254 return -EINVAL;
255}
256
257/**
258 * loopback_edge_show() - Get the edge type for loopback device
259 * @d: Linux device structure
260 * @attr: Device attribute structure
261 * @buf: Output buffer
262 *
263 * This function is used to get the loopback device edge runtime
264 * by reading the loopback_edge node.
265 */
266static ssize_t loopback_edge_show(struct device *d,
267 struct device_attribute *attr,
268 char *buf)
269{
270 struct smd_pkt_dev *smd_pkt_devp;
271
272 mutex_lock(&smd_pkt_dev_lock_lha1);
273 list_for_each_entry(smd_pkt_devp, &smd_pkt_dev_list, dev_list) {
274 if (smd_pkt_devp->devicep == d) {
275 mutex_unlock(&smd_pkt_dev_lock_lha1);
276 return snprintf(buf, PAGE_SIZE, "%d\n",
277 smd_pkt_devp->edge);
278 }
279 }
280 mutex_unlock(&smd_pkt_dev_lock_lha1);
281 pr_err("%s: unable to match device to valid smd_pkt port\n", __func__);
282 return -EINVAL;
283
284}
285
286static DEVICE_ATTR(loopback_edge, 0664, loopback_edge_show,
287 loopback_edge_store);
288
289static int notify_reset(struct smd_pkt_dev *smd_pkt_devp)
290{
291 smd_pkt_devp->do_reset_notification = 0;
292
293 return -ENETRESET;
294}
295
296static void clean_and_signal(struct smd_pkt_dev *smd_pkt_devp)
297{
298 smd_pkt_devp->do_reset_notification = 1;
299 smd_pkt_devp->has_reset = 1;
300
301 smd_pkt_devp->is_open = 0;
302
303 wake_up(&smd_pkt_devp->ch_read_wait_queue);
304 wake_up(&smd_pkt_devp->ch_write_wait_queue);
305 wake_up_interruptible(&smd_pkt_devp->ch_opened_wait_queue);
306 D_STATUS("%s smd_pkt_dev id:%d\n", __func__, smd_pkt_devp->i);
307}
308
309static void loopback_probe_worker(struct work_struct *work)
310{
311
312 /* Wait for the modem SMSM to be inited for the SMD
313 ** Loopback channel to be allocated at the modem. Since
314 ** the wait need to be done atmost once, using msleep
315 ** doesn't degrade the performance.
316 */
317 if (!is_modem_smsm_inited())
318 schedule_delayed_work(&loopback_work, msecs_to_jiffies(1000));
319 else
320 smsm_change_state(SMSM_APPS_STATE,
321 0, SMSM_SMD_LOOPBACK);
322
323}
324
325static void packet_arrival_worker(struct work_struct *work)
326{
327 struct smd_pkt_dev *smd_pkt_devp;
328 unsigned long flags;
329
330 smd_pkt_devp = container_of(work, struct smd_pkt_dev,
331 packet_arrival_work);
332 mutex_lock(&smd_pkt_devp->ch_lock);
333 spin_lock_irqsave(&smd_pkt_devp->pa_spinlock, flags);
334 if (smd_pkt_devp->ch && smd_pkt_devp->ws_locked) {
335 D_READ("%s locking smd_pkt_dev id:%d wakeup source\n",
336 __func__, smd_pkt_devp->i);
337 /*
338 * Keep system awake long enough to allow userspace client
339 * to process the packet.
340 */
341 __pm_wakeup_event(&smd_pkt_devp->pa_ws, WAKEUPSOURCE_TIMEOUT);
342 }
343 spin_unlock_irqrestore(&smd_pkt_devp->pa_spinlock, flags);
344 mutex_unlock(&smd_pkt_devp->ch_lock);
345}
346
347static long smd_pkt_ioctl(struct file *file, unsigned int cmd,
348 unsigned long arg)
349{
350 int ret;
351 struct smd_pkt_dev *smd_pkt_devp;
352 uint32_t val;
353
354 smd_pkt_devp = file->private_data;
355 if (!smd_pkt_devp)
356 return -EINVAL;
357
358 mutex_lock(&smd_pkt_devp->ch_lock);
359 switch (cmd) {
360 case TIOCMGET:
Arun Kumar Neelakantam011248b2018-03-09 14:57:51 +0530361 smd_pkt_devp->sigs_updated = false;
Arun Kumar Neelakantamd680a242017-11-02 21:14:53 +0530362 ret = smd_tiocmget(smd_pkt_devp->ch);
Arun Kumar Neelakantam011248b2018-03-09 14:57:51 +0530363 D_STATUS("%s TIOCMGET command on smd_pkt_dev id:%d [%d]\n",
364 __func__, smd_pkt_devp->i, ret);
365 if (ret > 0)
366 ret = put_user((uint32_t)ret, (uint32_t __user *)arg);
Arun Kumar Neelakantamd680a242017-11-02 21:14:53 +0530367 break;
368 case TIOCMSET:
369 ret = get_user(val, (uint32_t *)arg);
370 if (ret) {
371 pr_err("Error getting TIOCMSET value\n");
372 mutex_unlock(&smd_pkt_devp->ch_lock);
373 return ret;
374 }
375 D_STATUS("%s TIOCSET command on smd_pkt_dev id:%d arg[0x%x]\n",
376 __func__, smd_pkt_devp->i, val);
377 ret = smd_tiocmset(smd_pkt_devp->ch, val, ~val);
378 break;
379 case SMD_PKT_IOCTL_BLOCKING_WRITE:
380 ret = get_user(smd_pkt_devp->blocking_write, (int *)arg);
381 break;
382 default:
383 pr_err_ratelimited("%s: Unrecognized ioctl command %d\n",
384 __func__, cmd);
385 ret = -ENOIOCTLCMD;
386 }
387 mutex_unlock(&smd_pkt_devp->ch_lock);
388
389 return ret;
390}
391
392ssize_t smd_pkt_read(struct file *file,
393 char __user *_buf,
394 size_t count,
395 loff_t *ppos)
396{
397 int r;
398 int bytes_read;
399 int pkt_size;
400 struct smd_pkt_dev *smd_pkt_devp;
401 unsigned long flags;
402 void *buf;
403
404 smd_pkt_devp = file->private_data;
405
406 if (!smd_pkt_devp) {
407 pr_err_ratelimited("%s on NULL smd_pkt_dev\n", __func__);
408 return -EINVAL;
409 }
410
411 if (!smd_pkt_devp->ch) {
412 pr_err_ratelimited("%s on a closed smd_pkt_dev id:%d\n",
413 __func__, smd_pkt_devp->i);
414 return -EINVAL;
415 }
416
417 if (smd_pkt_devp->do_reset_notification) {
418 /* notify client that a reset occurred */
419 E_SMD_PKT_SSR(smd_pkt_devp);
420 return notify_reset(smd_pkt_devp);
421 }
422 D_READ("Begin %s on smd_pkt_dev id:%d buffer_size %zu\n",
423 __func__, smd_pkt_devp->i, count);
424
425 buf = kmalloc(count, GFP_KERNEL);
426 if (!buf)
427 return -ENOMEM;
428
429wait_for_packet:
430 r = wait_event_interruptible(smd_pkt_devp->ch_read_wait_queue,
431 !smd_pkt_devp->ch ||
432 (smd_cur_packet_size(smd_pkt_devp->ch) > 0
433 && smd_read_avail(smd_pkt_devp->ch)) ||
434 smd_pkt_devp->has_reset);
435
436 mutex_lock(&smd_pkt_devp->rx_lock);
437 if (smd_pkt_devp->has_reset) {
438 mutex_unlock(&smd_pkt_devp->rx_lock);
439 E_SMD_PKT_SSR(smd_pkt_devp);
440 kfree(buf);
441 return notify_reset(smd_pkt_devp);
442 }
443
444 if (!smd_pkt_devp->ch) {
445 mutex_unlock(&smd_pkt_devp->rx_lock);
446 pr_err_ratelimited("%s on a closed smd_pkt_dev id:%d\n",
447 __func__, smd_pkt_devp->i);
448 kfree(buf);
449 return -EINVAL;
450 }
451
452 if (r < 0) {
453 mutex_unlock(&smd_pkt_devp->rx_lock);
454 /* qualify error message */
455 if (r != -ERESTARTSYS) {
456 /* we get this anytime a signal comes in */
457 pr_err_ratelimited("%s: wait_event_interruptible on smd_pkt_dev id:%d ret %i\n",
458 __func__, smd_pkt_devp->i, r);
459 }
460 kfree(buf);
461 return r;
462 }
463
464 /* Here we have a whole packet waiting for us */
465 pkt_size = smd_cur_packet_size(smd_pkt_devp->ch);
466
467 if (!pkt_size) {
468 pr_err_ratelimited("%s: No data on smd_pkt_dev id:%d, False wakeup\n",
469 __func__, smd_pkt_devp->i);
470 mutex_unlock(&smd_pkt_devp->rx_lock);
471 goto wait_for_packet;
472 }
473
474 if (pkt_size < 0) {
475 pr_err_ratelimited("%s: Error %d obtaining packet size for Channel %s",
476 __func__, pkt_size, smd_pkt_devp->ch_name);
477 kfree(buf);
478 return pkt_size;
479 }
480
481 if ((uint32_t)pkt_size > count) {
482 pr_err_ratelimited("%s: failure on smd_pkt_dev id: %d - packet size %d > buffer size %zu,",
483 __func__, smd_pkt_devp->i,
484 pkt_size, count);
485 mutex_unlock(&smd_pkt_devp->rx_lock);
486 kfree(buf);
487 return -ETOOSMALL;
488 }
489
490 bytes_read = 0;
491 do {
492 r = smd_read(smd_pkt_devp->ch,
493 (buf + bytes_read),
494 (pkt_size - bytes_read));
495 if (r < 0) {
496 mutex_unlock(&smd_pkt_devp->rx_lock);
497 if (smd_pkt_devp->has_reset) {
498 E_SMD_PKT_SSR(smd_pkt_devp);
499 return notify_reset(smd_pkt_devp);
500 }
501 pr_err_ratelimited("%s Error while reading %d\n",
502 __func__, r);
503 kfree(buf);
504 return r;
505 }
506 bytes_read += r;
507 if (pkt_size != bytes_read)
508 wait_event(smd_pkt_devp->ch_read_wait_queue,
509 smd_read_avail(smd_pkt_devp->ch) ||
510 smd_pkt_devp->has_reset);
511 if (smd_pkt_devp->has_reset) {
512 mutex_unlock(&smd_pkt_devp->rx_lock);
513 E_SMD_PKT_SSR(smd_pkt_devp);
514 kfree(buf);
515 return notify_reset(smd_pkt_devp);
516 }
517 } while (pkt_size != bytes_read);
518 mutex_unlock(&smd_pkt_devp->rx_lock);
519
520 mutex_lock(&smd_pkt_devp->ch_lock);
521 spin_lock_irqsave(&smd_pkt_devp->pa_spinlock, flags);
522 if (smd_pkt_devp->poll_mode &&
523 !smd_cur_packet_size(smd_pkt_devp->ch)) {
524 __pm_relax(&smd_pkt_devp->pa_ws);
525 smd_pkt_devp->ws_locked = 0;
526 smd_pkt_devp->poll_mode = 0;
527 D_READ("%s unlocked smd_pkt_dev id:%d wakeup_source\n",
528 __func__, smd_pkt_devp->i);
529 }
530 spin_unlock_irqrestore(&smd_pkt_devp->pa_spinlock, flags);
531 mutex_unlock(&smd_pkt_devp->ch_lock);
532
533 r = copy_to_user(_buf, buf, bytes_read);
534 if (r) {
535 kfree(buf);
536 return -EFAULT;
537 }
538 D_READ("Finished %s on smd_pkt_dev id:%d %d bytes\n",
539 __func__, smd_pkt_devp->i, bytes_read);
540 kfree(buf);
541
542 /* check and wakeup read threads waiting on this device */
543 check_and_wakeup_reader(smd_pkt_devp);
544
545 return bytes_read;
546}
547
548ssize_t smd_pkt_write(struct file *file,
549 const char __user *_buf,
550 size_t count,
551 loff_t *ppos)
552{
553 int r = 0, bytes_written;
554 struct smd_pkt_dev *smd_pkt_devp;
555 DEFINE_WAIT(write_wait);
556 void *buf;
557
558 smd_pkt_devp = file->private_data;
559
560 if (!smd_pkt_devp) {
561 pr_err_ratelimited("%s on NULL smd_pkt_dev\n", __func__);
562 return -EINVAL;
563 }
564
565 if (!smd_pkt_devp->ch) {
566 pr_err_ratelimited("%s on a closed smd_pkt_dev id:%d\n",
567 __func__, smd_pkt_devp->i);
568 return -EINVAL;
569 }
570
571 if (smd_pkt_devp->do_reset_notification || smd_pkt_devp->has_reset) {
572 E_SMD_PKT_SSR(smd_pkt_devp);
573 /* notify client that a reset occurred */
574 return notify_reset(smd_pkt_devp);
575 }
576 D_WRITE("Begin %s on smd_pkt_dev id:%d data_size %zu\n",
577 __func__, smd_pkt_devp->i, count);
578
579 buf = kmalloc(count, GFP_KERNEL);
580 if (!buf)
581 return -ENOMEM;
582
583 r = copy_from_user(buf, _buf, count);
584 if (r) {
585 kfree(buf);
586 return -EFAULT;
587 }
588
589 mutex_lock(&smd_pkt_devp->tx_lock);
590 if (!smd_pkt_devp->blocking_write) {
591 if (smd_write_avail(smd_pkt_devp->ch) < count) {
592 pr_err_ratelimited("%s: Not enough space in smd_pkt_dev id:%d\n",
593 __func__, smd_pkt_devp->i);
594 mutex_unlock(&smd_pkt_devp->tx_lock);
595 kfree(buf);
596 return -ENOMEM;
597 }
598 }
599
600 r = smd_write_start(smd_pkt_devp->ch, count);
601 if (r < 0) {
602 mutex_unlock(&smd_pkt_devp->tx_lock);
603 pr_err_ratelimited("%s: Error:%d in smd_pkt_dev id:%d @ smd_write_start\n",
604 __func__, r, smd_pkt_devp->i);
605 kfree(buf);
606 return r;
607 }
608
609 bytes_written = 0;
610 do {
611 prepare_to_wait(&smd_pkt_devp->ch_write_wait_queue,
612 &write_wait, TASK_UNINTERRUPTIBLE);
613 if (!smd_write_segment_avail(smd_pkt_devp->ch) &&
614 !smd_pkt_devp->has_reset) {
615 smd_enable_read_intr(smd_pkt_devp->ch);
616 schedule();
617 }
618 finish_wait(&smd_pkt_devp->ch_write_wait_queue, &write_wait);
619 smd_disable_read_intr(smd_pkt_devp->ch);
620
621 if (smd_pkt_devp->has_reset) {
622 mutex_unlock(&smd_pkt_devp->tx_lock);
623 E_SMD_PKT_SSR(smd_pkt_devp);
624 kfree(buf);
625 return notify_reset(smd_pkt_devp);
626 }
627 r = smd_write_segment(smd_pkt_devp->ch,
628 (void *)(buf + bytes_written),
629 (count - bytes_written));
630 if (r < 0) {
631 mutex_unlock(&smd_pkt_devp->tx_lock);
632 if (smd_pkt_devp->has_reset) {
633 E_SMD_PKT_SSR(smd_pkt_devp);
634 return notify_reset(smd_pkt_devp);
635 }
636 pr_err_ratelimited("%s on smd_pkt_dev id:%d failed r:%d\n",
637 __func__, smd_pkt_devp->i, r);
638 kfree(buf);
639 return r;
640 }
641 bytes_written += r;
642 } while (bytes_written != count);
643 smd_write_end(smd_pkt_devp->ch);
644 mutex_unlock(&smd_pkt_devp->tx_lock);
645 D_WRITE("Finished %s on smd_pkt_dev id:%d %zu bytes\n",
646 __func__, smd_pkt_devp->i, count);
647
648 kfree(buf);
649 return count;
650}
651
652static unsigned int smd_pkt_poll(struct file *file, poll_table *wait)
653{
654 struct smd_pkt_dev *smd_pkt_devp;
655 unsigned int mask = 0;
656
657 smd_pkt_devp = file->private_data;
658 if (!smd_pkt_devp) {
659 pr_err_ratelimited("%s on a NULL device\n", __func__);
660 return POLLERR;
661 }
662
663 smd_pkt_devp->poll_mode = 1;
664 poll_wait(file, &smd_pkt_devp->ch_read_wait_queue, wait);
665 mutex_lock(&smd_pkt_devp->ch_lock);
666 if (smd_pkt_devp->has_reset || !smd_pkt_devp->ch) {
667 mutex_unlock(&smd_pkt_devp->ch_lock);
668 return POLLERR;
669 }
670
671 if (smd_read_avail(smd_pkt_devp->ch)) {
672 mask |= POLLIN | POLLRDNORM;
673 D_POLL("%s sets POLLIN for smd_pkt_dev id: %d\n",
674 __func__, smd_pkt_devp->i);
675 }
Arun Kumar Neelakantam011248b2018-03-09 14:57:51 +0530676
677 if (smd_pkt_devp->sigs_updated) {
678 mask |= POLLPRI;
679 D_POLL("%s sets POLLPRI for smd_pkt_dev id: %d\n",
680 __func__, smd_pkt_devp->i);
681 }
Arun Kumar Neelakantamd680a242017-11-02 21:14:53 +0530682 mutex_unlock(&smd_pkt_devp->ch_lock);
683
684 return mask;
685}
686
687static void check_and_wakeup_reader(struct smd_pkt_dev *smd_pkt_devp)
688{
689 int sz;
690 unsigned long flags;
691
692 if (!smd_pkt_devp) {
693 pr_err("%s on a NULL device\n", __func__);
694 return;
695 }
696
697 if (!smd_pkt_devp->ch) {
698 pr_err("%s on a closed smd_pkt_dev id:%d\n",
699 __func__, smd_pkt_devp->i);
700 return;
701 }
702
703 sz = smd_cur_packet_size(smd_pkt_devp->ch);
704 if (sz == 0) {
705 D_READ("%s: No packet in smd_pkt_dev id:%d\n",
706 __func__, smd_pkt_devp->i);
707 return;
708 }
709 if (!smd_read_avail(smd_pkt_devp->ch)) {
710 D_READ(
711 "%s: packet size is %d in smd_pkt_dev id:%d - but the data isn't here\n",
712 __func__, sz, smd_pkt_devp->i);
713 return;
714 }
715
716 /* here we have a packet of size sz ready */
717 spin_lock_irqsave(&smd_pkt_devp->pa_spinlock, flags);
718 __pm_stay_awake(&smd_pkt_devp->pa_ws);
719 smd_pkt_devp->ws_locked = 1;
720 spin_unlock_irqrestore(&smd_pkt_devp->pa_spinlock, flags);
721 wake_up(&smd_pkt_devp->ch_read_wait_queue);
722 schedule_work(&smd_pkt_devp->packet_arrival_work);
723 D_READ("%s: wake_up smd_pkt_dev id:%d\n", __func__, smd_pkt_devp->i);
724}
725
726static void check_and_wakeup_writer(struct smd_pkt_dev *smd_pkt_devp)
727{
728 int sz;
729
730 if (!smd_pkt_devp) {
731 pr_err("%s on a NULL device\n", __func__);
732 return;
733 }
734
735 if (!smd_pkt_devp->ch) {
736 pr_err("%s on a closed smd_pkt_dev id:%d\n",
737 __func__, smd_pkt_devp->i);
738 return;
739 }
740
741 sz = smd_write_segment_avail(smd_pkt_devp->ch);
742 if (sz) {
743 D_WRITE("%s: %d bytes write space in smd_pkt_dev id:%d\n",
744 __func__, sz, smd_pkt_devp->i);
745 smd_disable_read_intr(smd_pkt_devp->ch);
746 wake_up(&smd_pkt_devp->ch_write_wait_queue);
747 }
748}
749
750static void ch_notify(void *priv, unsigned int event)
751{
752 struct smd_pkt_dev *smd_pkt_devp = priv;
753
754 if (smd_pkt_devp->ch == 0) {
755 if (event != SMD_EVENT_CLOSE)
756 pr_err("%s on a closed smd_pkt_dev id:%d\n",
757 __func__, smd_pkt_devp->i);
758 return;
759 }
760
761 switch (event) {
762 case SMD_EVENT_DATA: {
763 D_STATUS("%s: DATA event in smd_pkt_dev id:%d\n",
764 __func__, smd_pkt_devp->i);
765 check_and_wakeup_reader(smd_pkt_devp);
766 if (smd_pkt_devp->blocking_write)
767 check_and_wakeup_writer(smd_pkt_devp);
768 break;
769 }
770 case SMD_EVENT_OPEN:
771 D_STATUS("%s: OPEN event in smd_pkt_dev id:%d\n",
772 __func__, smd_pkt_devp->i);
773 smd_pkt_devp->has_reset = 0;
774 smd_pkt_devp->is_open = 1;
775 wake_up_interruptible(&smd_pkt_devp->ch_opened_wait_queue);
776 break;
777 case SMD_EVENT_CLOSE:
778 D_STATUS("%s: CLOSE event in smd_pkt_dev id:%d\n",
779 __func__, smd_pkt_devp->i);
780 smd_pkt_devp->is_open = 0;
781 /* put port into reset state */
782 clean_and_signal(smd_pkt_devp);
783 if (!strcmp(smd_pkt_devp->ch_name, "LOOPBACK"))
784 schedule_delayed_work(&loopback_work,
785 msecs_to_jiffies(1000));
786 break;
Arun Kumar Neelakantam011248b2018-03-09 14:57:51 +0530787 case SMD_EVENT_STATUS:
788 smd_pkt_devp->sigs_updated = true;
789 break;
Arun Kumar Neelakantamd680a242017-11-02 21:14:53 +0530790 }
791}
792
793static int smd_pkt_dummy_probe(struct platform_device *pdev)
794{
795 struct smd_pkt_dev *smd_pkt_devp;
796
797 mutex_lock(&smd_pkt_dev_lock_lha1);
798 list_for_each_entry(smd_pkt_devp, &smd_pkt_dev_list, dev_list) {
799 if (smd_pkt_devp->edge == pdev->id
800 && !strcmp(pdev->name, smd_pkt_devp->ch_name)) {
801 complete_all(&smd_pkt_devp->ch_allocated);
802 D_STATUS("%s allocated SMD ch for smd_pkt_dev id:%d\n",
803 __func__, smd_pkt_devp->i);
804 break;
805 }
806 }
807 mutex_unlock(&smd_pkt_dev_lock_lha1);
808 return 0;
809}
810
811static uint32_t is_modem_smsm_inited(void)
812{
813 uint32_t modem_state;
814 uint32_t ready_state = (SMSM_INIT | SMSM_SMDINIT);
815
816 modem_state = smsm_get_state(SMSM_MODEM_STATE);
817 return (modem_state & ready_state) == ready_state;
818}
819
820/**
821 * smd_pkt_add_driver() - Add platform drivers for smd pkt device
822 *
823 * @smd_pkt_devp: pointer to the smd pkt device structure
824 *
825 * @returns: 0 for success, standard Linux error code otherwise
826 *
827 * This function is used to register platform driver once for all
828 * smd pkt devices which have same names and increment the reference
829 * count for 2nd to nth devices.
830 */
831static int smd_pkt_add_driver(struct smd_pkt_dev *smd_pkt_devp)
832{
833 int r = 0;
834 struct smd_pkt_driver *smd_pkt_driverp;
835 struct smd_pkt_driver *item;
836
837 if (!smd_pkt_devp) {
838 pr_err("%s on a NULL device\n", __func__);
839 return -EINVAL;
840 }
841 D_STATUS("Begin %s on smd_pkt_ch[%s]\n", __func__,
842 smd_pkt_devp->ch_name);
843
844 mutex_lock(&smd_pkt_driver_lock_lha1);
845 list_for_each_entry(item, &smd_pkt_driver_list, list) {
846 if (!strcmp(item->pdriver_name, smd_pkt_devp->ch_name)) {
847 D_STATUS("%s:%s Already Platform driver reg. cnt:%d\n",
848 __func__, smd_pkt_devp->ch_name, item->ref_cnt);
849 ++item->ref_cnt;
850 goto exit;
851 }
852 }
853
854 smd_pkt_driverp = kzalloc(sizeof(*smd_pkt_driverp), GFP_KERNEL);
855 if (IS_ERR_OR_NULL(smd_pkt_driverp)) {
856 pr_err("%s: kzalloc() failed for smd_pkt_driver[%s]\n",
857 __func__, smd_pkt_devp->ch_name);
858 r = -ENOMEM;
859 goto exit;
860 }
861
862 smd_pkt_driverp->driver.probe = smd_pkt_dummy_probe;
863 scnprintf(smd_pkt_driverp->pdriver_name, SMD_MAX_CH_NAME_LEN,
864 "%s", smd_pkt_devp->ch_name);
865 smd_pkt_driverp->driver.driver.name = smd_pkt_driverp->pdriver_name;
866 smd_pkt_driverp->driver.driver.owner = THIS_MODULE;
867 r = platform_driver_register(&smd_pkt_driverp->driver);
868 if (r) {
869 pr_err("%s: %s Platform driver reg. failed\n",
870 __func__, smd_pkt_devp->ch_name);
871 kfree(smd_pkt_driverp);
872 goto exit;
873 }
874 ++smd_pkt_driverp->ref_cnt;
875 list_add(&smd_pkt_driverp->list, &smd_pkt_driver_list);
876
877exit:
878 D_STATUS("End %s on smd_pkt_ch[%s]\n", __func__, smd_pkt_devp->ch_name);
879 mutex_unlock(&smd_pkt_driver_lock_lha1);
880 return r;
881}
882
883/**
884 * smd_pkt_remove_driver() - Remove the platform drivers for smd pkt device
885 *
886 * @smd_pkt_devp: pointer to the smd pkt device structure
887 *
888 * This function is used to decrement the reference count on
889 * platform drivers for smd pkt devices and removes the drivers
890 * when the reference count becomes zero.
891 */
892static void smd_pkt_remove_driver(struct smd_pkt_dev *smd_pkt_devp)
893{
894 struct smd_pkt_driver *smd_pkt_driverp;
895 bool found_item = false;
896
897 if (!smd_pkt_devp) {
898 pr_err("%s on a NULL device\n", __func__);
899 return;
900 }
901
902 D_STATUS("Begin %s on smd_pkt_ch[%s]\n", __func__,
903 smd_pkt_devp->ch_name);
904 mutex_lock(&smd_pkt_driver_lock_lha1);
905 list_for_each_entry(smd_pkt_driverp, &smd_pkt_driver_list, list) {
906 if (!strcmp(smd_pkt_driverp->pdriver_name,
907 smd_pkt_devp->ch_name)) {
908 found_item = true;
909 D_STATUS("%s:%s Platform driver cnt:%d\n",
910 __func__, smd_pkt_devp->ch_name,
911 smd_pkt_driverp->ref_cnt);
912 if (smd_pkt_driverp->ref_cnt > 0)
913 --smd_pkt_driverp->ref_cnt;
914 else
915 pr_warn("%s reference count <= 0\n", __func__);
916 break;
917 }
918 }
919 if (!found_item)
920 pr_err("%s:%s No item found in list.\n",
921 __func__, smd_pkt_devp->ch_name);
922
923 if (found_item && smd_pkt_driverp->ref_cnt == 0) {
924 platform_driver_unregister(&smd_pkt_driverp->driver);
925 smd_pkt_driverp->driver.probe = NULL;
926 list_del(&smd_pkt_driverp->list);
927 kfree(smd_pkt_driverp);
928 }
929 mutex_unlock(&smd_pkt_driver_lock_lha1);
930 D_STATUS("End %s on smd_pkt_ch[%s]\n", __func__, smd_pkt_devp->ch_name);
931}
932
933int smd_pkt_open(struct inode *inode, struct file *file)
934{
935 int r = 0;
936 struct smd_pkt_dev *smd_pkt_devp;
937 const char *peripheral = NULL;
938
939 smd_pkt_devp = container_of(inode->i_cdev, struct smd_pkt_dev, cdev);
940
941 if (!smd_pkt_devp) {
942 pr_err_ratelimited("%s on a NULL device\n", __func__);
943 return -EINVAL;
944 }
945 D_STATUS("Begin %s on smd_pkt_dev id:%d\n", __func__, smd_pkt_devp->i);
946
947 file->private_data = smd_pkt_devp;
948
949 mutex_lock(&smd_pkt_devp->ch_lock);
950 if (smd_pkt_devp->ch == 0) {
951 unsigned int open_wait_rem;
952
953 open_wait_rem = smd_pkt_devp->open_modem_wait * 1000;
954 reinit_completion(&smd_pkt_devp->ch_allocated);
955
956 r = smd_pkt_add_driver(smd_pkt_devp);
957 if (r) {
958 pr_err_ratelimited("%s: %s Platform driver reg. failed\n",
959 __func__, smd_pkt_devp->ch_name);
960 goto out;
961 }
962
963 peripheral = smd_edge_to_pil_str(smd_pkt_devp->edge);
964 if (!IS_ERR_OR_NULL(peripheral)) {
965 smd_pkt_devp->pil = subsystem_get(peripheral);
966 if (IS_ERR(smd_pkt_devp->pil)) {
967 r = PTR_ERR(smd_pkt_devp->pil);
968 pr_err_ratelimited("%s failed on smd_pkt_dev id:%d - subsystem_get failed for %s\n",
969 __func__, smd_pkt_devp->i, peripheral);
970 /*
971 * Sleep inorder to reduce the frequency of
972 * retry by user-space modules and to avoid
973 * possible watchdog bite.
974 */
975 msleep(open_wait_rem);
976 goto release_pd;
977 }
978 }
979
980 /* Wait for the modem SMSM to be inited for the SMD
981 ** Loopback channel to be allocated at the modem. Since
982 ** the wait need to be done atmost once, using msleep
983 ** doesn't degrade the performance.
984 */
985 if (!strcmp(smd_pkt_devp->ch_name, "LOOPBACK")) {
986 if (!is_modem_smsm_inited())
987 msleep(5000);
988 smsm_change_state(SMSM_APPS_STATE,
989 0, SMSM_SMD_LOOPBACK);
990 msleep(100);
991 }
992
993 /*
994 * Wait for a packet channel to be allocated so we know
995 * the modem is ready enough.
996 */
997 if (open_wait_rem) {
998 r = wait_for_completion_interruptible_timeout(
999 &smd_pkt_devp->ch_allocated,
1000 msecs_to_jiffies(open_wait_rem));
1001 if (r >= 0)
1002 open_wait_rem = jiffies_to_msecs(r);
1003 if (r == 0)
1004 r = -ETIMEDOUT;
1005 if (r == -ERESTARTSYS) {
1006 pr_info_ratelimited("%s: wait on smd_pkt_dev id:%d allocation interrupted\n",
1007 __func__, smd_pkt_devp->i);
1008 goto release_pil;
1009 }
1010 if (r < 0) {
1011 pr_err_ratelimited("%s: wait on smd_pkt_dev id:%d allocation failed rc:%d\n",
1012 __func__, smd_pkt_devp->i, r);
1013 goto release_pil;
1014 }
1015 }
1016
1017 r = smd_named_open_on_edge(smd_pkt_devp->ch_name,
1018 smd_pkt_devp->edge,
1019 &smd_pkt_devp->ch,
1020 smd_pkt_devp,
1021 ch_notify);
1022 if (r < 0) {
1023 pr_err_ratelimited("%s: %s open failed %d\n", __func__,
1024 smd_pkt_devp->ch_name, r);
1025 goto release_pil;
1026 }
1027
1028 open_wait_rem = max_t(unsigned int, 2000, open_wait_rem);
1029 r = wait_event_interruptible_timeout(
1030 smd_pkt_devp->ch_opened_wait_queue,
1031 smd_pkt_devp->is_open,
1032 msecs_to_jiffies(open_wait_rem));
1033 if (r == 0)
1034 r = -ETIMEDOUT;
1035
1036 if (r < 0) {
1037 /* close the ch to sync smd's state with smd_pkt */
1038 smd_close(smd_pkt_devp->ch);
1039 smd_pkt_devp->ch = NULL;
1040 }
1041
1042 if (r == -ERESTARTSYS) {
1043 pr_info_ratelimited("%s: wait on smd_pkt_dev id:%d OPEN interrupted\n",
1044 __func__, smd_pkt_devp->i);
1045 } else if (r < 0) {
1046 pr_err_ratelimited("%s: wait on smd_pkt_dev id:%d OPEN event failed rc:%d\n",
1047 __func__, smd_pkt_devp->i, r);
1048 } else if (!smd_pkt_devp->is_open) {
1049 pr_err_ratelimited("%s: Invalid OPEN event on smd_pkt_dev id:%d\n",
1050 __func__, smd_pkt_devp->i);
1051 r = -ENODEV;
1052 } else {
1053 smd_disable_read_intr(smd_pkt_devp->ch);
1054 smd_pkt_devp->ch_size =
1055 smd_write_avail(smd_pkt_devp->ch);
1056 r = 0;
1057 smd_pkt_devp->ref_cnt++;
1058 D_STATUS("Finished %s on smd_pkt_dev id:%d\n",
1059 __func__, smd_pkt_devp->i);
1060 }
1061 } else {
1062 smd_pkt_devp->ref_cnt++;
1063 }
1064release_pil:
1065 if (peripheral && (r < 0)) {
1066 subsystem_put(smd_pkt_devp->pil);
1067 smd_pkt_devp->pil = NULL;
1068 }
1069
1070release_pd:
1071 if (r < 0)
1072 smd_pkt_remove_driver(smd_pkt_devp);
1073out:
1074 mutex_unlock(&smd_pkt_devp->ch_lock);
1075
1076
1077 return r;
1078}
1079
1080int smd_pkt_release(struct inode *inode, struct file *file)
1081{
1082 int r = 0;
1083 struct smd_pkt_dev *smd_pkt_devp = file->private_data;
1084 unsigned long flags;
1085
1086 if (!smd_pkt_devp) {
1087 pr_err_ratelimited("%s on a NULL device\n", __func__);
1088 return -EINVAL;
1089 }
1090 D_STATUS("Begin %s on smd_pkt_dev id:%d\n",
1091 __func__, smd_pkt_devp->i);
1092
1093 mutex_lock(&smd_pkt_devp->ch_lock);
1094 mutex_lock(&smd_pkt_devp->rx_lock);
1095 mutex_lock(&smd_pkt_devp->tx_lock);
1096 if (smd_pkt_devp->ref_cnt > 0)
1097 smd_pkt_devp->ref_cnt--;
1098
1099 if (smd_pkt_devp->ch != 0 && smd_pkt_devp->ref_cnt == 0) {
1100 clean_and_signal(smd_pkt_devp);
1101 r = smd_close(smd_pkt_devp->ch);
1102 smd_pkt_devp->ch = 0;
1103 smd_pkt_devp->blocking_write = 0;
1104 smd_pkt_devp->poll_mode = 0;
1105 smd_pkt_remove_driver(smd_pkt_devp);
1106 if (smd_pkt_devp->pil)
1107 subsystem_put(smd_pkt_devp->pil);
1108 smd_pkt_devp->has_reset = 0;
1109 smd_pkt_devp->do_reset_notification = 0;
1110 spin_lock_irqsave(&smd_pkt_devp->pa_spinlock, flags);
1111 if (smd_pkt_devp->ws_locked) {
1112 __pm_relax(&smd_pkt_devp->pa_ws);
1113 smd_pkt_devp->ws_locked = 0;
1114 }
1115 spin_unlock_irqrestore(&smd_pkt_devp->pa_spinlock, flags);
Arun Kumar Neelakantam011248b2018-03-09 14:57:51 +05301116 smd_pkt_devp->sigs_updated = false;
Arun Kumar Neelakantamd680a242017-11-02 21:14:53 +05301117 }
1118 mutex_unlock(&smd_pkt_devp->tx_lock);
1119 mutex_unlock(&smd_pkt_devp->rx_lock);
1120 mutex_unlock(&smd_pkt_devp->ch_lock);
1121
1122 if (flush_work(&smd_pkt_devp->packet_arrival_work))
1123 D_STATUS("%s: Flushed work for smd_pkt_dev id:%d\n", __func__,
1124 smd_pkt_devp->i);
1125
1126 D_STATUS("Finished %s on smd_pkt_dev id:%d\n",
1127 __func__, smd_pkt_devp->i);
1128
1129 return r;
1130}
1131
1132static const struct file_operations smd_pkt_fops = {
1133 .owner = THIS_MODULE,
1134 .open = smd_pkt_open,
1135 .release = smd_pkt_release,
1136 .read = smd_pkt_read,
1137 .write = smd_pkt_write,
1138 .poll = smd_pkt_poll,
1139 .unlocked_ioctl = smd_pkt_ioctl,
1140 .compat_ioctl = smd_pkt_ioctl,
1141};
1142
1143static int smd_pkt_init_add_device(struct smd_pkt_dev *smd_pkt_devp, int i)
1144{
1145 int r = 0;
1146
1147 smd_pkt_devp->i = i;
1148
1149 init_waitqueue_head(&smd_pkt_devp->ch_read_wait_queue);
1150 init_waitqueue_head(&smd_pkt_devp->ch_write_wait_queue);
1151 smd_pkt_devp->is_open = 0;
1152 smd_pkt_devp->poll_mode = 0;
1153 smd_pkt_devp->ws_locked = 0;
1154 init_waitqueue_head(&smd_pkt_devp->ch_opened_wait_queue);
1155
1156 spin_lock_init(&smd_pkt_devp->pa_spinlock);
1157 mutex_init(&smd_pkt_devp->ch_lock);
1158 mutex_init(&smd_pkt_devp->rx_lock);
1159 mutex_init(&smd_pkt_devp->tx_lock);
1160 wakeup_source_init(&smd_pkt_devp->pa_ws, smd_pkt_devp->dev_name);
1161 INIT_WORK(&smd_pkt_devp->packet_arrival_work, packet_arrival_worker);
1162 init_completion(&smd_pkt_devp->ch_allocated);
1163
1164 cdev_init(&smd_pkt_devp->cdev, &smd_pkt_fops);
1165 smd_pkt_devp->cdev.owner = THIS_MODULE;
1166
1167 r = cdev_add(&smd_pkt_devp->cdev, (smd_pkt_number + i), 1);
1168 if (r) {
1169 pr_err("%s: cdev_add() failed for smd_pkt_dev id:%d ret:%i\n",
1170 __func__, i, r);
1171 return r;
1172 }
1173
1174 smd_pkt_devp->devicep =
1175 device_create(smd_pkt_classp,
1176 NULL,
1177 (smd_pkt_number + i),
1178 NULL,
1179 smd_pkt_devp->dev_name);
1180
1181 if (IS_ERR_OR_NULL(smd_pkt_devp->devicep)) {
1182 pr_err("%s: device_create() failed for smd_pkt_dev id:%d\n",
1183 __func__, i);
1184 r = -ENOMEM;
1185 cdev_del(&smd_pkt_devp->cdev);
1186 wakeup_source_trash(&smd_pkt_devp->pa_ws);
1187 return r;
1188 }
1189 if (device_create_file(smd_pkt_devp->devicep,
1190 &dev_attr_open_timeout))
1191 pr_err("%s: unable to create device attr for smd_pkt_dev id:%d\n",
1192 __func__, i);
1193
1194 if (!strcmp(smd_pkt_devp->ch_name, "LOOPBACK")) {
1195 if (device_create_file(smd_pkt_devp->devicep,
1196 &dev_attr_loopback_edge))
1197 pr_err("%s: unable to create device attr for smd_pkt_dev id:%d\n",
1198 __func__, i);
1199 }
1200 mutex_lock(&smd_pkt_dev_lock_lha1);
1201 list_add(&smd_pkt_devp->dev_list, &smd_pkt_dev_list);
1202 mutex_unlock(&smd_pkt_dev_lock_lha1);
1203
1204 return r;
1205}
1206
1207static void smd_pkt_core_deinit(void)
1208{
1209 struct smd_pkt_dev *smd_pkt_devp;
1210 struct smd_pkt_dev *index;
1211
1212 mutex_lock(&smd_pkt_dev_lock_lha1);
1213 list_for_each_entry_safe(smd_pkt_devp, index, &smd_pkt_dev_list,
1214 dev_list) {
1215 cdev_del(&smd_pkt_devp->cdev);
1216 list_del(&smd_pkt_devp->dev_list);
1217 device_destroy(smd_pkt_classp,
1218 MKDEV(MAJOR(smd_pkt_number), smd_pkt_devp->i));
1219 kfree(smd_pkt_devp);
1220 }
1221 mutex_unlock(&smd_pkt_dev_lock_lha1);
1222
1223 if (!IS_ERR_OR_NULL(smd_pkt_classp))
1224 class_destroy(smd_pkt_classp);
1225
1226 unregister_chrdev_region(MAJOR(smd_pkt_number), num_smd_pkt_ports);
1227}
1228
1229static int smd_pkt_alloc_chrdev_region(void)
1230{
1231 int r = alloc_chrdev_region(&smd_pkt_number,
1232 0,
1233 num_smd_pkt_ports,
1234 DEVICE_NAME);
1235
1236 if (r) {
1237 pr_err("%s: alloc_chrdev_region() failed ret:%i\n",
1238 __func__, r);
1239 return r;
1240 }
1241
1242 smd_pkt_classp = class_create(THIS_MODULE, DEVICE_NAME);
1243 if (IS_ERR(smd_pkt_classp)) {
1244 pr_err("%s: class_create() failed ENOMEM\n", __func__);
1245 r = -ENOMEM;
1246 unregister_chrdev_region(MAJOR(smd_pkt_number),
1247 num_smd_pkt_ports);
1248 return r;
1249 }
1250
1251 return 0;
1252}
1253
1254static int parse_smdpkt_devicetree(struct device_node *node,
1255 struct smd_pkt_dev *smd_pkt_devp)
1256{
1257 int edge;
1258 char *key;
1259 const char *ch_name;
1260 const char *dev_name;
1261 const char *remote_ss;
1262
1263 key = "qcom,smdpkt-remote";
1264 remote_ss = of_get_property(node, key, NULL);
1265 if (!remote_ss)
1266 goto error;
1267
1268 edge = smd_remote_ss_to_edge(remote_ss);
1269 if (edge < 0)
1270 goto error;
1271
1272 smd_pkt_devp->edge = edge;
1273 D_STATUS("%s: %s = %d", __func__, key, edge);
1274
1275 key = "qcom,smdpkt-port-name";
1276 ch_name = of_get_property(node, key, NULL);
1277 if (!ch_name)
1278 goto error;
1279
1280 strlcpy(smd_pkt_devp->ch_name, ch_name, SMD_MAX_CH_NAME_LEN);
1281 D_STATUS("%s ch_name = %s\n", __func__, ch_name);
1282
1283 key = "qcom,smdpkt-dev-name";
1284 dev_name = of_get_property(node, key, NULL);
1285 if (!dev_name)
1286 goto error;
1287
1288 strlcpy(smd_pkt_devp->dev_name, dev_name, SMD_MAX_CH_NAME_LEN);
1289 D_STATUS("%s dev_name = %s\n", __func__, dev_name);
1290
1291 return 0;
1292
1293error:
1294 pr_err("%s: missing key: %s\n", __func__, key);
1295 return -ENODEV;
1296
1297}
1298
1299static int smd_pkt_devicetree_init(struct platform_device *pdev)
1300{
1301 int ret;
1302 int i = 0;
1303 struct device_node *node;
1304 struct smd_pkt_dev *smd_pkt_devp;
1305 int subnode_num = 0;
1306
1307 for_each_child_of_node(pdev->dev.of_node, node)
1308 ++subnode_num;
1309
1310 num_smd_pkt_ports = subnode_num;
1311
1312 ret = smd_pkt_alloc_chrdev_region();
1313 if (ret) {
1314 pr_err("%s: smd_pkt_alloc_chrdev_region() failed ret:%i\n",
1315 __func__, ret);
1316 return ret;
1317 }
1318
1319 for_each_child_of_node(pdev->dev.of_node, node) {
1320 smd_pkt_devp = kzalloc(sizeof(struct smd_pkt_dev), GFP_KERNEL);
1321 if (IS_ERR_OR_NULL(smd_pkt_devp)) {
1322 pr_err("%s: kzalloc() failed for smd_pkt_dev id:%d\n",
1323 __func__, i);
1324 ret = -ENOMEM;
1325 goto error_destroy;
1326 }
1327
1328 ret = parse_smdpkt_devicetree(node, smd_pkt_devp);
1329 if (ret) {
1330 pr_err(" failed to parse_smdpkt_devicetree %d\n", i);
1331 kfree(smd_pkt_devp);
1332 goto error_destroy;
1333 }
1334
1335 ret = smd_pkt_init_add_device(smd_pkt_devp, i);
1336 if (ret < 0) {
1337 pr_err("add device failed for idx:%d ret=%d\n", i, ret);
1338 kfree(smd_pkt_devp);
1339 goto error_destroy;
1340 }
1341 i++;
1342 }
1343
1344 INIT_DELAYED_WORK(&loopback_work, loopback_probe_worker);
1345
1346 D_STATUS("SMD Packet Port Driver Initialized.\n");
1347 return 0;
1348
1349error_destroy:
1350 smd_pkt_core_deinit();
1351 return ret;
1352}
1353
1354static int msm_smd_pkt_probe(struct platform_device *pdev)
1355{
1356 int ret;
1357
1358 if (pdev) {
1359 if (pdev->dev.of_node) {
1360 D_STATUS("%s device tree implementation\n", __func__);
1361 ret = smd_pkt_devicetree_init(pdev);
1362 if (ret)
1363 pr_err("%s: device tree init failed\n",
1364 __func__);
1365 }
1366 }
1367
1368 return 0;
1369}
1370
1371static const struct of_device_id msm_smd_pkt_match_table[] = {
1372 { .compatible = "qcom,smdpkt" },
1373 {},
1374};
1375
1376static struct platform_driver msm_smd_pkt_driver = {
1377 .probe = msm_smd_pkt_probe,
1378 .driver = {
1379 .name = MODULE_NAME,
1380 .owner = THIS_MODULE,
1381 .of_match_table = msm_smd_pkt_match_table,
1382 },
1383};
1384
1385static int __init smd_pkt_init(void)
1386{
1387 int rc;
1388
1389 INIT_LIST_HEAD(&smd_pkt_dev_list);
1390 INIT_LIST_HEAD(&smd_pkt_driver_list);
1391 rc = platform_driver_register(&msm_smd_pkt_driver);
1392 if (rc) {
1393 pr_err("%s: msm_smd_driver register failed %d\n",
1394 __func__, rc);
1395 return rc;
1396 }
1397
1398 smd_pkt_ilctxt = ipc_log_context_create(SMD_PKT_IPC_LOG_PAGE_CNT,
1399 "smd_pkt", 0);
1400 return 0;
1401}
1402
1403static void __exit smd_pkt_cleanup(void)
1404{
1405 smd_pkt_core_deinit();
1406}
1407
1408module_init(smd_pkt_init);
1409module_exit(smd_pkt_cleanup);
1410
1411MODULE_DESCRIPTION("MSM Shared Memory Packet Port");
1412MODULE_LICENSE("GPL v2");