[RAMEN9610-20413][9610] wlbt: SCSC Driver version 10.6.1.0
[GitHub/MotorolaMobilityLLC/kernel-slsi.git] / drivers / misc / samsung / scsc / scsc_log_collector_mmap.c
1 /****************************************************************************
2 *
3 * Copyright (c) 2014 - 2018 Samsung Electronics Co., Ltd. All rights reserved
4 *
5 ****************************************************************************/
6 #include <linux/kernel.h>
7 #include <linux/module.h>
8 #include <linux/moduleparam.h>
9 #include <linux/cdev.h>
10 #include <linux/device.h>
11 #include <linux/uaccess.h>
12 #include <linux/mm.h>
13 #include <scsc/scsc_log_collector.h>
14 #include "scsc_log_collector_mmap.h"
15
16 #define DEVICE_NAME "scsc_log_collector"
17 #define N_MINORS 1
18
19 struct class *scsc_log_collector_class;
20 struct cdev scsc_log_collector_dev[N_MINORS];
21 dev_t dev_num;
22
23 static int scsc_log_collector_mmap_open(struct inode *inode, struct file *filp)
24 {
25 pr_info("scsc_log_collector_mmap_open\n");
26 return 0;
27 }
28
29 static int scsc_log_collector_release(struct inode *inode, struct file *filp)
30 {
31 pr_info("scsc_log_collector_release\n");
32 return 0;
33 }
34
35 static int scsc_log_collector_mmap(struct file *filp, struct vm_area_struct *vma)
36 {
37 unsigned long start = vma->vm_start;
38 unsigned long size = vma->vm_end - vma->vm_start;
39 unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
40 unsigned long page, pos;
41 unsigned char *buf;
42
43 if (size > SCSC_LOG_COLLECT_MAX_SIZE)
44 return -EINVAL;
45 if (offset > SCSC_LOG_COLLECT_MAX_SIZE - size)
46 return -EINVAL;
47
48 buf = scsc_log_collector_get_buffer();
49 if (!buf) {
50 pr_err("No buffer mapped\n");
51 return -ENOMEM;
52 }
53
54 pos = (unsigned long)buf + offset;
55
56 pr_info("scsc_log_collector_mmap size:%lu offset %ld\n", size, offset);
57
58 while (size > 0) {
59 page = vmalloc_to_pfn((void *)pos);
60 if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED))
61 return -EAGAIN;
62
63 start += PAGE_SIZE;
64 pos += PAGE_SIZE;
65 if (size > PAGE_SIZE)
66 size -= PAGE_SIZE;
67 else
68 size = 0;
69 }
70
71 return 0;
72 }
73
74 static const struct file_operations scsc_log_collector_mmap_fops = {
75 .owner = THIS_MODULE,
76 .open = scsc_log_collector_mmap_open,
77 .mmap = scsc_log_collector_mmap,
78 .release = scsc_log_collector_release,
79 };
80
81 int scsc_log_collector_mmap_create(void)
82 {
83 struct device *dev;
84 int i;
85 int ret;
86 dev_t curr_dev;
87
88 /* Request the kernel for N_MINOR devices */
89 ret = alloc_chrdev_region(&dev_num, 0, N_MINORS, "scsc_log_collector");
90 if (ret) {
91 pr_err("alloc_chrdev_region failed");
92 goto error;
93 }
94
95 /* Create a class : appears at /sys/class */
96 scsc_log_collector_class = class_create(THIS_MODULE, "scsc_log_collector_class");
97 if (IS_ERR(scsc_log_collector_class)) {
98 ret = PTR_ERR(scsc_log_collector_class);
99 goto error_class;
100 }
101
102 /* Initialize and create each of the device(cdev) */
103 for (i = 0; i < N_MINORS; i++) {
104 /* Associate the cdev with a set of file_operations */
105 cdev_init(&scsc_log_collector_dev[i], &scsc_log_collector_mmap_fops);
106
107 ret = cdev_add(&scsc_log_collector_dev[i], dev_num, 1);
108 if (ret)
109 pr_err("cdev_add failed");
110
111 scsc_log_collector_dev[i].owner = THIS_MODULE;
112 /* Build up the current device number. To be used further */
113 dev = device_create(scsc_log_collector_class, NULL, dev_num, NULL, "scsc_log_collector_%d", i);
114 if (IS_ERR(dev)) {
115 pr_err("device_create failed");
116 ret = PTR_ERR(dev);
117 cdev_del(&scsc_log_collector_dev[i]);
118 continue;
119 }
120 curr_dev = MKDEV(MAJOR(dev_num), MINOR(dev_num) + i);
121 }
122
123 return 0;
124
125 error_class:
126 unregister_chrdev_region(dev_num, N_MINORS);
127 error:
128 return 0;
129 }
130
131 int scsc_log_collector_mmap_destroy(void)
132 {
133 int i;
134
135 device_destroy(scsc_log_collector_class, dev_num);
136 for (i = 0; i < N_MINORS; i++)
137 cdev_del(&scsc_log_collector_dev[i]);
138 class_destroy(scsc_log_collector_class);
139 unregister_chrdev_region(dev_num, N_MINORS);
140 return 0;
141 }