1 /****************************************************************************
3 * Copyright (c) 2014 - 2018 Samsung Electronics Co., Ltd. All rights reserved
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>
13 #include <scsc/scsc_log_collector.h>
14 #include "scsc_log_collector_mmap.h"
16 #define DEVICE_NAME "scsc_log_collector"
19 struct class *scsc_log_collector_class
;
20 struct cdev scsc_log_collector_dev
[N_MINORS
];
23 static int scsc_log_collector_mmap_open(struct inode
*inode
, struct file
*filp
)
25 pr_info("scsc_log_collector_mmap_open\n");
29 static int scsc_log_collector_release(struct inode
*inode
, struct file
*filp
)
31 pr_info("scsc_log_collector_release\n");
35 static int scsc_log_collector_mmap(struct file
*filp
, struct vm_area_struct
*vma
)
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
;
43 if (size
> SCSC_LOG_COLLECT_MAX_SIZE
)
45 if (offset
> SCSC_LOG_COLLECT_MAX_SIZE
- size
)
48 buf
= scsc_log_collector_get_buffer();
50 pr_err("No buffer mapped\n");
54 pos
= (unsigned long)buf
+ offset
;
56 pr_info("scsc_log_collector_mmap size:%lu offset %ld\n", size
, offset
);
59 page
= vmalloc_to_pfn((void *)pos
);
60 if (remap_pfn_range(vma
, start
, page
, PAGE_SIZE
, PAGE_SHARED
))
74 static const struct file_operations scsc_log_collector_mmap_fops
= {
76 .open
= scsc_log_collector_mmap_open
,
77 .mmap
= scsc_log_collector_mmap
,
78 .release
= scsc_log_collector_release
,
81 int scsc_log_collector_mmap_create(void)
88 /* Request the kernel for N_MINOR devices */
89 ret
= alloc_chrdev_region(&dev_num
, 0, N_MINORS
, "scsc_log_collector");
91 pr_err("alloc_chrdev_region failed");
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
);
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
);
107 ret
= cdev_add(&scsc_log_collector_dev
[i
], dev_num
, 1);
109 pr_err("cdev_add failed");
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
);
115 pr_err("device_create failed");
117 cdev_del(&scsc_log_collector_dev
[i
]);
120 curr_dev
= MKDEV(MAJOR(dev_num
), MINOR(dev_num
) + i
);
126 unregister_chrdev_region(dev_num
, N_MINORS
);
131 int scsc_log_collector_mmap_destroy(void)
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
);