2 * Copyright (C) 2012 Spreadtrum Communications Inc.
4 * This software is licensed under the terms of the GNU General Public
5 * License version 2, as published by the Free Software Foundation, and
6 * may be copied, distributed, and modified under those terms.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
14 #include <linux/kernel.h>
15 #include <linux/module.h>
16 #include <linux/genalloc.h>
18 #include <linux/debugfs.h>
19 #include <linux/seq_file.h>
20 #include <linux/slab.h>
21 #include <linux/list.h>
22 #include <linux/sched.h>
24 #include <linux/sipc.h>
27 struct list_head smem_head;
38 struct list_head smem_list;
39 struct task_struct *task;
44 static struct smem_pool mem_pool;
46 int smem_init(uint32_t addr, uint32_t size)
48 struct smem_pool *spool = &mem_pool;
51 spool->size = PAGE_ALIGN(size);
52 atomic_set(&spool->used, 0);
53 spin_lock_init(&spool->lock);
54 INIT_LIST_HEAD(&spool->smem_head);
56 /* allocator block size is times of pages */
57 spool->gen = gen_pool_create(PAGE_SHIFT, -1);
59 printk(KERN_ERR "Failed to create smem gen pool!\n");
63 if (gen_pool_add(spool->gen, spool->addr, spool->size, -1) != 0) {
64 printk(KERN_ERR "Failed to add smem gen pool!\n");
71 /* ****************************************************************** */
73 uint32_t smem_alloc(uint32_t size)
75 struct smem_pool *spool = &mem_pool;
76 struct smem_record *recd;
80 recd = kzalloc(sizeof(struct smem_record), GFP_KERNEL);
82 printk(KERN_ERR "failed to alloc smem record\n");
87 size = PAGE_ALIGN(size);
88 addr = gen_pool_alloc(spool->gen, size);
90 printk(KERN_ERR "failed to alloc smem from gen pool\n");
95 /* record smem alloc info */
96 atomic_add(size, &spool->used);
100 spin_lock_irqsave(&spool->lock, flags);
101 list_add_tail(&recd->smem_list, &spool->smem_head);
102 spin_unlock_irqrestore(&spool->lock, flags);
108 void smem_free(uint32_t addr, uint32_t size)
110 struct smem_pool *spool = &mem_pool;
111 struct smem_record *recd, *next;
114 size = PAGE_ALIGN(size);
115 atomic_sub(size, &spool->used);
116 gen_pool_free(spool->gen, addr, size);
117 /* delete record node from list */
118 spin_lock_irqsave(&spool->lock, flags);
119 list_for_each_entry_safe(recd, next, &spool->smem_head, smem_list) {
120 if (recd->addr == addr) {
121 list_del(&recd->smem_list);
126 spin_unlock_irqrestore(&spool->lock, flags);
129 #ifdef CONFIG_DEBUG_FS
130 static int smem_debug_show(struct seq_file *m, void *private)
132 struct smem_pool *spool = &mem_pool;
133 struct smem_record *recd;
137 fsize = gen_pool_avail(spool->gen);
139 seq_printf(m, "smem pool infomation:\n");
140 seq_printf(m, "phys_addr=0x%x, total=0x%x, used=0x%x, free=0x%x\n",
141 spool->addr, spool->size, spool->used, fsize);
142 seq_printf(m, "smem record list:\n");
144 spin_lock_irqsave(&spool->lock, flags);
145 list_for_each_entry(recd, &spool->smem_head, smem_list) {
146 seq_printf(m, "task %s: pid=%u, addr=0x%x, size=0x%x\n",
147 recd->task->comm, recd->task->pid, recd->addr, recd->size);
149 spin_unlock_irqrestore(&spool->lock, flags);
153 static int smem_debug_open(struct inode *inode, struct file *file)
155 return single_open(file, smem_debug_show, inode->i_private);
158 static const struct file_operations smem_debug_fops = {
159 .open = smem_debug_open,
162 .release = single_release,
165 int smem_init_debugfs(void *root)
169 debugfs_create_file("smem", S_IRUGO, (struct dentry *)root, NULL, &smem_debug_fops);
173 #endif //endof CONFIG_DEBUG_FS
175 EXPORT_SYMBOL(smem_alloc);
176 EXPORT_SYMBOL(smem_free);
178 MODULE_AUTHOR("Chen Gaopeng");
179 MODULE_DESCRIPTION("SIPC/SMEM driver");
180 MODULE_LICENSE("GPL");