tracing: Fix uninitialized variable of tracing/trace output
[pandora-kernel.git] / drivers / staging / dream / pmem.c
1 /* drivers/android/pmem.c
2  *
3  * Copyright (C) 2007 Google, Inc.
4  *
5  * This software is licensed under the terms of the GNU General Public
6  * License version 2, as published by the Free Software Foundation, and
7  * may be copied, distributed, and modified under those terms.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  */
15
16 #include <linux/miscdevice.h>
17 #include <linux/platform_device.h>
18 #include <linux/fs.h>
19 #include <linux/file.h>
20 #include <linux/mm.h>
21 #include <linux/list.h>
22 #include <linux/debugfs.h>
23 #include <linux/android_pmem.h>
24 #include <linux/mempolicy.h>
25 #include <linux/sched.h>
26 #include <asm/io.h>
27 #include <asm/uaccess.h>
28 #include <asm/cacheflush.h>
29
30 #define PMEM_MAX_DEVICES 10
31 #define PMEM_MAX_ORDER 128
32 #define PMEM_MIN_ALLOC PAGE_SIZE
33
34 #define PMEM_DEBUG 1
35
36 /* indicates that a refernce to this file has been taken via get_pmem_file,
37  * the file should not be released until put_pmem_file is called */
38 #define PMEM_FLAGS_BUSY 0x1
39 /* indicates that this is a suballocation of a larger master range */
40 #define PMEM_FLAGS_CONNECTED ( 0x1 << 1 )
41 /* indicates this is a master and not a sub allocation and that it is mmaped */
42 #define PMEM_FLAGS_MASTERMAP ( 0x1 << 2 )
43 /* submap and unsubmap flags indicate:
44  * 00: subregion has never been mmaped
45  * 10: subregion has been mmaped, reference to the mm was taken
46  * 11: subretion has ben released, refernece to the mm still held
47  * 01: subretion has been released, reference to the mm has been released
48  */
49 #define PMEM_FLAGS_SUBMAP ( 0x1 << 3 )
50 #define PMEM_FLAGS_UNSUBMAP ( 0x1 << 4 )
51
52
53 struct pmem_data {
54         /* in alloc mode: an index into the bitmap
55          * in no_alloc mode: the size of the allocation */
56         int index;
57         /* see flags above for descriptions */
58         unsigned int flags;
59         /* protects this data field, if the mm_mmap sem will be held at the
60          * same time as this sem, the mm sem must be taken first (as this is
61          * the order for vma_open and vma_close ops */
62         struct rw_semaphore sem;
63         /* info about the mmaping process */
64         struct vm_area_struct *vma;
65         /* task struct of the mapping process */
66         struct task_struct *task;
67         /* process id of teh mapping process */
68         pid_t pid;
69         /* file descriptor of the master */
70         int master_fd;
71         /* file struct of the master */
72         struct file *master_file;
73         /* a list of currently available regions if this is a suballocation */
74         struct list_head region_list;
75         /* a linked list of data so we can access them for debugging */
76         struct list_head list;
77 #if PMEM_DEBUG
78         int ref;
79 #endif
80 };
81
82 struct pmem_bits {
83         unsigned allocated:1;           /* 1 if allocated, 0 if free */
84         unsigned order:7;               /* size of the region in pmem space */
85 };
86
87 struct pmem_region_node {
88         struct pmem_region region;
89         struct list_head list;
90 };
91
92 #define PMEM_DEBUG_MSGS 0
93 #if PMEM_DEBUG_MSGS
94 #define DLOG(fmt, args...) \
95         do { printk(KERN_INFO "[%s:%s:%d] "fmt, __FILE__, __func__, __LINE__, \
96                     ##args); } \
97         while (0)
98 #else
99 #define DLOG(x...) do {} while (0)
100 #endif
101
102 struct pmem_info {
103         struct miscdevice dev;
104         /* physical start address of the remaped pmem space */
105         unsigned long base;
106         /* vitual start address of the remaped pmem space */
107         unsigned char __iomem *vbase;
108         /* total size of the pmem space */
109         unsigned long size;
110         /* number of entries in the pmem space */
111         unsigned long num_entries;
112         /* pfn of the garbage page in memory */
113         unsigned long garbage_pfn;
114         /* index of the garbage page in the pmem space */
115         int garbage_index;
116         /* the bitmap for the region indicating which entries are allocated
117          * and which are free */
118         struct pmem_bits *bitmap;
119         /* indicates the region should not be managed with an allocator */
120         unsigned no_allocator;
121         /* indicates maps of this region should be cached, if a mix of
122          * cached and uncached is desired, set this and open the device with
123          * O_SYNC to get an uncached region */
124         unsigned cached;
125         unsigned buffered;
126         /* in no_allocator mode the first mapper gets the whole space and sets
127          * this flag */
128         unsigned allocated;
129         /* for debugging, creates a list of pmem file structs, the
130          * data_list_sem should be taken before pmem_data->sem if both are
131          * needed */
132         struct semaphore data_list_sem;
133         struct list_head data_list;
134         /* pmem_sem protects the bitmap array
135          * a write lock should be held when modifying entries in bitmap
136          * a read lock should be held when reading data from bits or
137          * dereferencing a pointer into bitmap
138          *
139          * pmem_data->sem protects the pmem data of a particular file
140          * Many of the function that require the pmem_data->sem have a non-
141          * locking version for when the caller is already holding that sem.
142          *
143          * IF YOU TAKE BOTH LOCKS TAKE THEM IN THIS ORDER:
144          * down(pmem_data->sem) => down(bitmap_sem)
145          */
146         struct rw_semaphore bitmap_sem;
147
148         long (*ioctl)(struct file *, unsigned int, unsigned long);
149         int (*release)(struct inode *, struct file *);
150 };
151
152 static struct pmem_info pmem[PMEM_MAX_DEVICES];
153 static int id_count;
154
155 #define PMEM_IS_FREE(id, index) ( !(pmem[id].bitmap[index].allocated) )
156 #define PMEM_ORDER(id, index) pmem[id].bitmap[index].order
157 #define PMEM_BUDDY_INDEX(id, index) (index ^ (1 << PMEM_ORDER(id, index)))
158 #define PMEM_NEXT_INDEX(id, index) (index + (1 << PMEM_ORDER(id, index)))
159 #define PMEM_OFFSET(index) (index * PMEM_MIN_ALLOC)
160 #define PMEM_START_ADDR(id, index) (PMEM_OFFSET(index) + pmem[id].base)
161 #define PMEM_LEN(id, index) ((1 << PMEM_ORDER(id, index)) * PMEM_MIN_ALLOC)
162 #define PMEM_END_ADDR(id, index) (PMEM_START_ADDR(id, index) + \
163         PMEM_LEN(id, index))
164 #define PMEM_START_VADDR(id, index) (PMEM_OFFSET(id, index) + pmem[id].vbase)
165 #define PMEM_END_VADDR(id, index) (PMEM_START_VADDR(id, index) + \
166         PMEM_LEN(id, index))
167 #define PMEM_REVOKED(data) (data->flags & PMEM_FLAGS_REVOKED)
168 #define PMEM_IS_PAGE_ALIGNED(addr) (!((addr) & (~PAGE_MASK)))
169 #define PMEM_IS_SUBMAP(data) ((data->flags & PMEM_FLAGS_SUBMAP) && \
170         (!(data->flags & PMEM_FLAGS_UNSUBMAP)))
171
172 static int pmem_release(struct inode *, struct file *);
173 static int pmem_mmap(struct file *, struct vm_area_struct *);
174 static int pmem_open(struct inode *, struct file *);
175 static long pmem_ioctl(struct file *, unsigned int, unsigned long);
176
177 struct file_operations pmem_fops = {
178         .release = pmem_release,
179         .mmap = pmem_mmap,
180         .open = pmem_open,
181         .unlocked_ioctl = pmem_ioctl,
182 };
183
184 static int get_id(struct file *file)
185 {
186         return MINOR(file->f_dentry->d_inode->i_rdev);
187 }
188
189 static int is_pmem_file(struct file *file)
190 {
191         int id;
192
193         if (unlikely(!file || !file->f_dentry || !file->f_dentry->d_inode))
194                 return 0;
195         id = get_id(file);
196         if (unlikely(id >= PMEM_MAX_DEVICES))
197                 return 0;
198         if (unlikely(file->f_dentry->d_inode->i_rdev !=
199              MKDEV(MISC_MAJOR, pmem[id].dev.minor)))
200                 return 0;
201         return 1;
202 }
203
204 static int has_allocation(struct file *file)
205 {
206         struct pmem_data *data;
207         /* check is_pmem_file first if not accessed via pmem_file_ops */
208
209         if (unlikely(!file->private_data))
210                 return 0;
211         data = (struct pmem_data *)file->private_data;
212         if (unlikely(data->index < 0))
213                 return 0;
214         return 1;
215 }
216
217 static int is_master_owner(struct file *file)
218 {
219         struct file *master_file;
220         struct pmem_data *data;
221         int put_needed, ret = 0;
222
223         if (!is_pmem_file(file) || !has_allocation(file))
224                 return 0;
225         data = (struct pmem_data *)file->private_data;
226         if (PMEM_FLAGS_MASTERMAP & data->flags)
227                 return 1;
228         master_file = fget_light(data->master_fd, &put_needed);
229         if (master_file && data->master_file == master_file)
230                 ret = 1;
231         fput_light(master_file, put_needed);
232         return ret;
233 }
234
235 static int pmem_free(int id, int index)
236 {
237         /* caller should hold the write lock on pmem_sem! */
238         int buddy, curr = index;
239         DLOG("index %d\n", index);
240
241         if (pmem[id].no_allocator) {
242                 pmem[id].allocated = 0;
243                 return 0;
244         }
245         /* clean up the bitmap, merging any buddies */
246         pmem[id].bitmap[curr].allocated = 0;
247         /* find a slots buddy Buddy# = Slot# ^ (1 << order)
248          * if the buddy is also free merge them
249          * repeat until the buddy is not free or end of the bitmap is reached
250          */
251         do {
252                 buddy = PMEM_BUDDY_INDEX(id, curr);
253                 if (PMEM_IS_FREE(id, buddy) &&
254                                 PMEM_ORDER(id, buddy) == PMEM_ORDER(id, curr)) {
255                         PMEM_ORDER(id, buddy)++;
256                         PMEM_ORDER(id, curr)++;
257                         curr = min(buddy, curr);
258                 } else {
259                         break;
260                 }
261         } while (curr < pmem[id].num_entries);
262
263         return 0;
264 }
265
266 static void pmem_revoke(struct file *file, struct pmem_data *data);
267
268 static int pmem_release(struct inode *inode, struct file *file)
269 {
270         struct pmem_data *data = (struct pmem_data *)file->private_data;
271         struct pmem_region_node *region_node;
272         struct list_head *elt, *elt2;
273         int id = get_id(file), ret = 0;
274
275
276         down(&pmem[id].data_list_sem);
277         /* if this file is a master, revoke all the memory in the connected
278          *  files */
279         if (PMEM_FLAGS_MASTERMAP & data->flags) {
280                 struct pmem_data *sub_data;
281                 list_for_each(elt, &pmem[id].data_list) {
282                         sub_data = list_entry(elt, struct pmem_data, list);
283                         down_read(&sub_data->sem);
284                         if (PMEM_IS_SUBMAP(sub_data) &&
285                             file == sub_data->master_file) {
286                                 up_read(&sub_data->sem);
287                                 pmem_revoke(file, sub_data);
288                         }  else
289                                 up_read(&sub_data->sem);
290                 }
291         }
292         list_del(&data->list);
293         up(&pmem[id].data_list_sem);
294
295
296         down_write(&data->sem);
297
298         /* if its not a conencted file and it has an allocation, free it */
299         if (!(PMEM_FLAGS_CONNECTED & data->flags) && has_allocation(file)) {
300                 down_write(&pmem[id].bitmap_sem);
301                 ret = pmem_free(id, data->index);
302                 up_write(&pmem[id].bitmap_sem);
303         }
304
305         /* if this file is a submap (mapped, connected file), downref the
306          * task struct */
307         if (PMEM_FLAGS_SUBMAP & data->flags)
308                 if (data->task) {
309                         put_task_struct(data->task);
310                         data->task = NULL;
311                 }
312
313         file->private_data = NULL;
314
315         list_for_each_safe(elt, elt2, &data->region_list) {
316                 region_node = list_entry(elt, struct pmem_region_node, list);
317                 list_del(elt);
318                 kfree(region_node);
319         }
320         BUG_ON(!list_empty(&data->region_list));
321
322         up_write(&data->sem);
323         kfree(data);
324         if (pmem[id].release)
325                 ret = pmem[id].release(inode, file);
326
327         return ret;
328 }
329
330 static int pmem_open(struct inode *inode, struct file *file)
331 {
332         struct pmem_data *data;
333         int id = get_id(file);
334         int ret = 0;
335
336         DLOG("current %u file %p(%d)\n", current->pid, file, file_count(file));
337         /* setup file->private_data to indicate its unmapped */
338         /*  you can only open a pmem device one time */
339         if (file->private_data != NULL)
340                 return -1;
341         data = kmalloc(sizeof(struct pmem_data), GFP_KERNEL);
342         if (!data) {
343                 printk("pmem: unable to allocate memory for pmem metadata.");
344                 return -1;
345         }
346         data->flags = 0;
347         data->index = -1;
348         data->task = NULL;
349         data->vma = NULL;
350         data->pid = 0;
351         data->master_file = NULL;
352 #if PMEM_DEBUG
353         data->ref = 0;
354 #endif
355         INIT_LIST_HEAD(&data->region_list);
356         init_rwsem(&data->sem);
357
358         file->private_data = data;
359         INIT_LIST_HEAD(&data->list);
360
361         down(&pmem[id].data_list_sem);
362         list_add(&data->list, &pmem[id].data_list);
363         up(&pmem[id].data_list_sem);
364         return ret;
365 }
366
367 static unsigned long pmem_order(unsigned long len)
368 {
369         int i;
370
371         len = (len + PMEM_MIN_ALLOC - 1)/PMEM_MIN_ALLOC;
372         len--;
373         for (i = 0; i < sizeof(len)*8; i++)
374                 if (len >> i == 0)
375                         break;
376         return i;
377 }
378
379 static int pmem_allocate(int id, unsigned long len)
380 {
381         /* caller should hold the write lock on pmem_sem! */
382         /* return the corresponding pdata[] entry */
383         int curr = 0;
384         int end = pmem[id].num_entries;
385         int best_fit = -1;
386         unsigned long order = pmem_order(len);
387
388         if (pmem[id].no_allocator) {
389                 DLOG("no allocator");
390                 if ((len > pmem[id].size) || pmem[id].allocated)
391                         return -1;
392                 pmem[id].allocated = 1;
393                 return len;
394         }
395
396         if (order > PMEM_MAX_ORDER)
397                 return -1;
398         DLOG("order %lx\n", order);
399
400         /* look through the bitmap:
401          *      if you find a free slot of the correct order use it
402          *      otherwise, use the best fit (smallest with size > order) slot
403          */
404         while (curr < end) {
405                 if (PMEM_IS_FREE(id, curr)) {
406                         if (PMEM_ORDER(id, curr) == (unsigned char)order) {
407                                 /* set the not free bit and clear others */
408                                 best_fit = curr;
409                                 break;
410                         }
411                         if (PMEM_ORDER(id, curr) > (unsigned char)order &&
412                             (best_fit < 0 ||
413                              PMEM_ORDER(id, curr) < PMEM_ORDER(id, best_fit)))
414                                 best_fit = curr;
415                 }
416                 curr = PMEM_NEXT_INDEX(id, curr);
417         }
418
419         /* if best_fit < 0, there are no suitable slots,
420          * return an error
421          */
422         if (best_fit < 0) {
423                 printk("pmem: no space left to allocate!\n");
424                 return -1;
425         }
426
427         /* now partition the best fit:
428          *      split the slot into 2 buddies of order - 1
429          *      repeat until the slot is of the correct order
430          */
431         while (PMEM_ORDER(id, best_fit) > (unsigned char)order) {
432                 int buddy;
433                 PMEM_ORDER(id, best_fit) -= 1;
434                 buddy = PMEM_BUDDY_INDEX(id, best_fit);
435                 PMEM_ORDER(id, buddy) = PMEM_ORDER(id, best_fit);
436         }
437         pmem[id].bitmap[best_fit].allocated = 1;
438         return best_fit;
439 }
440
441 static pgprot_t phys_mem_access_prot(struct file *file, pgprot_t vma_prot)
442 {
443         int id = get_id(file);
444 #ifdef pgprot_noncached
445         if (pmem[id].cached == 0 || file->f_flags & O_SYNC)
446                 return pgprot_noncached(vma_prot);
447 #endif
448 #ifdef pgprot_ext_buffered
449         else if (pmem[id].buffered)
450                 return pgprot_ext_buffered(vma_prot);
451 #endif
452         return vma_prot;
453 }
454
455 static unsigned long pmem_start_addr(int id, struct pmem_data *data)
456 {
457         if (pmem[id].no_allocator)
458                 return PMEM_START_ADDR(id, 0);
459         else
460                 return PMEM_START_ADDR(id, data->index);
461
462 }
463
464 static void *pmem_start_vaddr(int id, struct pmem_data *data)
465 {
466         return pmem_start_addr(id, data) - pmem[id].base + pmem[id].vbase;
467 }
468
469 static unsigned long pmem_len(int id, struct pmem_data *data)
470 {
471         if (pmem[id].no_allocator)
472                 return data->index;
473         else
474                 return PMEM_LEN(id, data->index);
475 }
476
477 static int pmem_map_garbage(int id, struct vm_area_struct *vma,
478                             struct pmem_data *data, unsigned long offset,
479                             unsigned long len)
480 {
481         int i, garbage_pages = len >> PAGE_SHIFT;
482
483         vma->vm_flags |= VM_IO | VM_RESERVED | VM_PFNMAP | VM_SHARED | VM_WRITE;
484         for (i = 0; i < garbage_pages; i++) {
485                 if (vm_insert_pfn(vma, vma->vm_start + offset + (i * PAGE_SIZE),
486                     pmem[id].garbage_pfn))
487                         return -EAGAIN;
488         }
489         return 0;
490 }
491
492 static int pmem_unmap_pfn_range(int id, struct vm_area_struct *vma,
493                                 struct pmem_data *data, unsigned long offset,
494                                 unsigned long len)
495 {
496         int garbage_pages;
497         DLOG("unmap offset %lx len %lx\n", offset, len);
498
499         BUG_ON(!PMEM_IS_PAGE_ALIGNED(len));
500
501         garbage_pages = len >> PAGE_SHIFT;
502         zap_page_range(vma, vma->vm_start + offset, len, NULL);
503         pmem_map_garbage(id, vma, data, offset, len);
504         return 0;
505 }
506
507 static int pmem_map_pfn_range(int id, struct vm_area_struct *vma,
508                               struct pmem_data *data, unsigned long offset,
509                               unsigned long len)
510 {
511         DLOG("map offset %lx len %lx\n", offset, len);
512         BUG_ON(!PMEM_IS_PAGE_ALIGNED(vma->vm_start));
513         BUG_ON(!PMEM_IS_PAGE_ALIGNED(vma->vm_end));
514         BUG_ON(!PMEM_IS_PAGE_ALIGNED(len));
515         BUG_ON(!PMEM_IS_PAGE_ALIGNED(offset));
516
517         if (io_remap_pfn_range(vma, vma->vm_start + offset,
518                 (pmem_start_addr(id, data) + offset) >> PAGE_SHIFT,
519                 len, vma->vm_page_prot)) {
520                 return -EAGAIN;
521         }
522         return 0;
523 }
524
525 static int pmem_remap_pfn_range(int id, struct vm_area_struct *vma,
526                               struct pmem_data *data, unsigned long offset,
527                               unsigned long len)
528 {
529         /* hold the mm semp for the vma you are modifying when you call this */
530         BUG_ON(!vma);
531         zap_page_range(vma, vma->vm_start + offset, len, NULL);
532         return pmem_map_pfn_range(id, vma, data, offset, len);
533 }
534
535 static void pmem_vma_open(struct vm_area_struct *vma)
536 {
537         struct file *file = vma->vm_file;
538         struct pmem_data *data = file->private_data;
539         int id = get_id(file);
540         /* this should never be called as we don't support copying pmem
541          * ranges via fork */
542         BUG_ON(!has_allocation(file));
543         down_write(&data->sem);
544         /* remap the garbage pages, forkers don't get access to the data */
545         pmem_unmap_pfn_range(id, vma, data, 0, vma->vm_start - vma->vm_end);
546         up_write(&data->sem);
547 }
548
549 static void pmem_vma_close(struct vm_area_struct *vma)
550 {
551         struct file *file = vma->vm_file;
552         struct pmem_data *data = file->private_data;
553
554         DLOG("current %u ppid %u file %p count %d\n", current->pid,
555              current->parent->pid, file, file_count(file));
556         if (unlikely(!is_pmem_file(file) || !has_allocation(file))) {
557                 printk(KERN_WARNING "pmem: something is very wrong, you are "
558                        "closing a vm backing an allocation that doesn't "
559                        "exist!\n");
560                 return;
561         }
562         down_write(&data->sem);
563         if (data->vma == vma) {
564                 data->vma = NULL;
565                 if ((data->flags & PMEM_FLAGS_CONNECTED) &&
566                     (data->flags & PMEM_FLAGS_SUBMAP))
567                         data->flags |= PMEM_FLAGS_UNSUBMAP;
568         }
569         /* the kernel is going to free this vma now anyway */
570         up_write(&data->sem);
571 }
572
573 static struct vm_operations_struct vm_ops = {
574         .open = pmem_vma_open,
575         .close = pmem_vma_close,
576 };
577
578 static int pmem_mmap(struct file *file, struct vm_area_struct *vma)
579 {
580         struct pmem_data *data;
581         int index;
582         unsigned long vma_size =  vma->vm_end - vma->vm_start;
583         int ret = 0, id = get_id(file);
584
585         if (vma->vm_pgoff || !PMEM_IS_PAGE_ALIGNED(vma_size)) {
586 #if PMEM_DEBUG
587                 printk(KERN_ERR "pmem: mmaps must be at offset zero, aligned"
588                                 " and a multiple of pages_size.\n");
589 #endif
590                 return -EINVAL;
591         }
592
593         data = (struct pmem_data *)file->private_data;
594         down_write(&data->sem);
595         /* check this file isn't already mmaped, for submaps check this file
596          * has never been mmaped */
597         if ((data->flags & PMEM_FLAGS_MASTERMAP) ||
598             (data->flags & PMEM_FLAGS_SUBMAP) ||
599             (data->flags & PMEM_FLAGS_UNSUBMAP)) {
600 #if PMEM_DEBUG
601                 printk(KERN_ERR "pmem: you can only mmap a pmem file once, "
602                        "this file is already mmaped. %x\n", data->flags);
603 #endif
604                 ret = -EINVAL;
605                 goto error;
606         }
607         /* if file->private_data == unalloced, alloc*/
608         if (data && data->index == -1) {
609                 down_write(&pmem[id].bitmap_sem);
610                 index = pmem_allocate(id, vma->vm_end - vma->vm_start);
611                 up_write(&pmem[id].bitmap_sem);
612                 data->index = index;
613         }
614         /* either no space was available or an error occured */
615         if (!has_allocation(file)) {
616                 ret = -EINVAL;
617                 printk("pmem: could not find allocation for map.\n");
618                 goto error;
619         }
620
621         if (pmem_len(id, data) < vma_size) {
622 #if PMEM_DEBUG
623                 printk(KERN_WARNING "pmem: mmap size [%lu] does not match"
624                        "size of backing region [%lu].\n", vma_size,
625                        pmem_len(id, data));
626 #endif
627                 ret = -EINVAL;
628                 goto error;
629         }
630
631         vma->vm_pgoff = pmem_start_addr(id, data) >> PAGE_SHIFT;
632         vma->vm_page_prot = phys_mem_access_prot(file, vma->vm_page_prot);
633
634         if (data->flags & PMEM_FLAGS_CONNECTED) {
635                 struct pmem_region_node *region_node;
636                 struct list_head *elt;
637                 if (pmem_map_garbage(id, vma, data, 0, vma_size)) {
638                         printk("pmem: mmap failed in kernel!\n");
639                         ret = -EAGAIN;
640                         goto error;
641                 }
642                 list_for_each(elt, &data->region_list) {
643                         region_node = list_entry(elt, struct pmem_region_node,
644                                                  list);
645                         DLOG("remapping file: %p %lx %lx\n", file,
646                                 region_node->region.offset,
647                                 region_node->region.len);
648                         if (pmem_remap_pfn_range(id, vma, data,
649                                                  region_node->region.offset,
650                                                  region_node->region.len)) {
651                                 ret = -EAGAIN;
652                                 goto error;
653                         }
654                 }
655                 data->flags |= PMEM_FLAGS_SUBMAP;
656                 get_task_struct(current->group_leader);
657                 data->task = current->group_leader;
658                 data->vma = vma;
659 #if PMEM_DEBUG
660                 data->pid = current->pid;
661 #endif
662                 DLOG("submmapped file %p vma %p pid %u\n", file, vma,
663                      current->pid);
664         } else {
665                 if (pmem_map_pfn_range(id, vma, data, 0, vma_size)) {
666                         printk(KERN_INFO "pmem: mmap failed in kernel!\n");
667                         ret = -EAGAIN;
668                         goto error;
669                 }
670                 data->flags |= PMEM_FLAGS_MASTERMAP;
671                 data->pid = current->pid;
672         }
673         vma->vm_ops = &vm_ops;
674 error:
675         up_write(&data->sem);
676         return ret;
677 }
678
679 /* the following are the api for accessing pmem regions by other drivers
680  * from inside the kernel */
681 int get_pmem_user_addr(struct file *file, unsigned long *start,
682                    unsigned long *len)
683 {
684         struct pmem_data *data;
685         if (!is_pmem_file(file) || !has_allocation(file)) {
686 #if PMEM_DEBUG
687                 printk(KERN_INFO "pmem: requested pmem data from invalid"
688                                   "file.\n");
689 #endif
690                 return -1;
691         }
692         data = (struct pmem_data *)file->private_data;
693         down_read(&data->sem);
694         if (data->vma) {
695                 *start = data->vma->vm_start;
696                 *len = data->vma->vm_end - data->vma->vm_start;
697         } else {
698                 *start = 0;
699                 *len = 0;
700         }
701         up_read(&data->sem);
702         return 0;
703 }
704
705 int get_pmem_addr(struct file *file, unsigned long *start,
706                   unsigned long *vstart, unsigned long *len)
707 {
708         struct pmem_data *data;
709         int id;
710
711         if (!is_pmem_file(file) || !has_allocation(file))
712                 return -1;
713
714         data = (struct pmem_data *)file->private_data;
715         if (data->index == -1) {
716 #if PMEM_DEBUG
717                 printk(KERN_INFO "pmem: requested pmem data from file with no "
718                        "allocation.\n");
719                 return -1;
720 #endif
721         }
722         id = get_id(file);
723
724         down_read(&data->sem);
725         *start = pmem_start_addr(id, data);
726         *len = pmem_len(id, data);
727         *vstart = (unsigned long)pmem_start_vaddr(id, data);
728         up_read(&data->sem);
729 #if PMEM_DEBUG
730         down_write(&data->sem);
731         data->ref++;
732         up_write(&data->sem);
733 #endif
734         return 0;
735 }
736
737 int get_pmem_file(int fd, unsigned long *start, unsigned long *vstart,
738                   unsigned long *len, struct file **filp)
739 {
740         struct file *file;
741
742         file = fget(fd);
743         if (unlikely(file == NULL)) {
744                 printk(KERN_INFO "pmem: requested data from file descriptor "
745                        "that doesn't exist.");
746                 return -1;
747         }
748
749         if (get_pmem_addr(file, start, vstart, len))
750                 goto end;
751
752         if (filp)
753                 *filp = file;
754         return 0;
755 end:
756         fput(file);
757         return -1;
758 }
759
760 void put_pmem_file(struct file *file)
761 {
762         struct pmem_data *data;
763         int id;
764
765         if (!is_pmem_file(file))
766                 return;
767         id = get_id(file);
768         data = (struct pmem_data *)file->private_data;
769 #if PMEM_DEBUG
770         down_write(&data->sem);
771         if (data->ref == 0) {
772                 printk("pmem: pmem_put > pmem_get %s (pid %d)\n",
773                        pmem[id].dev.name, data->pid);
774                 BUG();
775         }
776         data->ref--;
777         up_write(&data->sem);
778 #endif
779         fput(file);
780 }
781
782 void flush_pmem_file(struct file *file, unsigned long offset, unsigned long len)
783 {
784         struct pmem_data *data;
785         int id;
786         void *vaddr;
787         struct pmem_region_node *region_node;
788         struct list_head *elt;
789         void *flush_start, *flush_end;
790
791         if (!is_pmem_file(file) || !has_allocation(file))
792                 return;
793
794         id = get_id(file);
795         data = (struct pmem_data *)file->private_data;
796         if (!pmem[id].cached)
797                 return;
798
799         down_read(&data->sem);
800         vaddr = pmem_start_vaddr(id, data);
801         /* if this isn't a submmapped file, flush the whole thing */
802         if (unlikely(!(data->flags & PMEM_FLAGS_CONNECTED))) {
803                 dmac_flush_range(vaddr, vaddr + pmem_len(id, data));
804                 goto end;
805         }
806         /* otherwise, flush the region of the file we are drawing */
807         list_for_each(elt, &data->region_list) {
808                 region_node = list_entry(elt, struct pmem_region_node, list);
809                 if ((offset >= region_node->region.offset) &&
810                     ((offset + len) <= (region_node->region.offset +
811                         region_node->region.len))) {
812                         flush_start = vaddr + region_node->region.offset;
813                         flush_end = flush_start + region_node->region.len;
814                         dmac_flush_range(flush_start, flush_end);
815                         break;
816                 }
817         }
818 end:
819         up_read(&data->sem);
820 }
821
822 static int pmem_connect(unsigned long connect, struct file *file)
823 {
824         struct pmem_data *data = (struct pmem_data *)file->private_data;
825         struct pmem_data *src_data;
826         struct file *src_file;
827         int ret = 0, put_needed;
828
829         down_write(&data->sem);
830         /* retrieve the src file and check it is a pmem file with an alloc */
831         src_file = fget_light(connect, &put_needed);
832         DLOG("connect %p to %p\n", file, src_file);
833         if (!src_file) {
834                 printk(KERN_INFO "pmem: src file not found!\n");
835                 ret = -EINVAL;
836                 goto err_no_file;
837         }
838         if (unlikely(!is_pmem_file(src_file) || !has_allocation(src_file))) {
839                 printk(KERN_INFO "pmem: src file is not a pmem file or has no "
840                        "alloc!\n");
841                 ret = -EINVAL;
842                 goto err_bad_file;
843         }
844         src_data = (struct pmem_data *)src_file->private_data;
845
846         if (has_allocation(file) && (data->index != src_data->index)) {
847                 printk(KERN_INFO "pmem: file is already mapped but doesn't match this"
848                        " src_file!\n");
849                 ret = -EINVAL;
850                 goto err_bad_file;
851         }
852         data->index = src_data->index;
853         data->flags |= PMEM_FLAGS_CONNECTED;
854         data->master_fd = connect;
855         data->master_file = src_file;
856
857 err_bad_file:
858         fput_light(src_file, put_needed);
859 err_no_file:
860         up_write(&data->sem);
861         return ret;
862 }
863
864 static void pmem_unlock_data_and_mm(struct pmem_data *data,
865                                     struct mm_struct *mm)
866 {
867         up_write(&data->sem);
868         if (mm != NULL) {
869                 up_write(&mm->mmap_sem);
870                 mmput(mm);
871         }
872 }
873
874 static int pmem_lock_data_and_mm(struct file *file, struct pmem_data *data,
875                                  struct mm_struct **locked_mm)
876 {
877         int ret = 0;
878         struct mm_struct *mm = NULL;
879         *locked_mm = NULL;
880 lock_mm:
881         down_read(&data->sem);
882         if (PMEM_IS_SUBMAP(data)) {
883                 mm = get_task_mm(data->task);
884                 if (!mm) {
885 #if PMEM_DEBUG
886                         printk(KERN_DEBUG "pmem: can't remap task is gone!\n");
887 #endif
888                         up_read(&data->sem);
889                         return -1;
890                 }
891         }
892         up_read(&data->sem);
893
894         if (mm)
895                 down_write(&mm->mmap_sem);
896
897         down_write(&data->sem);
898         /* check that the file didn't get mmaped before we could take the
899          * data sem, this should be safe b/c you can only submap each file
900          * once */
901         if (PMEM_IS_SUBMAP(data) && !mm) {
902                 pmem_unlock_data_and_mm(data, mm);
903                 up_write(&data->sem);
904                 goto lock_mm;
905         }
906         /* now check that vma.mm is still there, it could have been
907          * deleted by vma_close before we could get the data->sem */
908         if ((data->flags & PMEM_FLAGS_UNSUBMAP) && (mm != NULL)) {
909                 /* might as well release this */
910                 if (data->flags & PMEM_FLAGS_SUBMAP) {
911                         put_task_struct(data->task);
912                         data->task = NULL;
913                         /* lower the submap flag to show the mm is gone */
914                         data->flags &= ~(PMEM_FLAGS_SUBMAP);
915                 }
916                 pmem_unlock_data_and_mm(data, mm);
917                 return -1;
918         }
919         *locked_mm = mm;
920         return ret;
921 }
922
923 int pmem_remap(struct pmem_region *region, struct file *file,
924                       unsigned operation)
925 {
926         int ret;
927         struct pmem_region_node *region_node;
928         struct mm_struct *mm = NULL;
929         struct list_head *elt, *elt2;
930         int id = get_id(file);
931         struct pmem_data *data = (struct pmem_data *)file->private_data;
932
933         /* pmem region must be aligned on a page boundry */
934         if (unlikely(!PMEM_IS_PAGE_ALIGNED(region->offset) ||
935                  !PMEM_IS_PAGE_ALIGNED(region->len))) {
936 #if PMEM_DEBUG
937                 printk(KERN_DEBUG "pmem: request for unaligned pmem suballocation "
938                        "%lx %lx\n", region->offset, region->len);
939 #endif
940                 return -EINVAL;
941         }
942
943         /* if userspace requests a region of len 0, there's nothing to do */
944         if (region->len == 0)
945                 return 0;
946
947         /* lock the mm and data */
948         ret = pmem_lock_data_and_mm(file, data, &mm);
949         if (ret)
950                 return 0;
951
952         /* only the owner of the master file can remap the client fds
953          * that back in it */
954         if (!is_master_owner(file)) {
955 #if PMEM_DEBUG
956                 printk("pmem: remap requested from non-master process\n");
957 #endif
958                 ret = -EINVAL;
959                 goto err;
960         }
961
962         /* check that the requested range is within the src allocation */
963         if (unlikely((region->offset > pmem_len(id, data)) ||
964                      (region->len > pmem_len(id, data)) ||
965                      (region->offset + region->len > pmem_len(id, data)))) {
966 #if PMEM_DEBUG
967                 printk(KERN_INFO "pmem: suballoc doesn't fit in src_file!\n");
968 #endif
969                 ret = -EINVAL;
970                 goto err;
971         }
972
973         if (operation == PMEM_MAP) {
974                 region_node = kmalloc(sizeof(struct pmem_region_node),
975                               GFP_KERNEL);
976                 if (!region_node) {
977                         ret = -ENOMEM;
978 #if PMEM_DEBUG
979                         printk(KERN_INFO "No space to allocate metadata!");
980 #endif
981                         goto err;
982                 }
983                 region_node->region = *region;
984                 list_add(&region_node->list, &data->region_list);
985         } else if (operation == PMEM_UNMAP) {
986                 int found = 0;
987                 list_for_each_safe(elt, elt2, &data->region_list) {
988                         region_node = list_entry(elt, struct pmem_region_node,
989                                       list);
990                         if (region->len == 0 ||
991                             (region_node->region.offset == region->offset &&
992                             region_node->region.len == region->len)) {
993                                 list_del(elt);
994                                 kfree(region_node);
995                                 found = 1;
996                         }
997                 }
998                 if (!found) {
999 #if PMEM_DEBUG
1000                         printk("pmem: Unmap region does not map any mapped "
1001                                 "region!");
1002 #endif
1003                         ret = -EINVAL;
1004                         goto err;
1005                 }
1006         }
1007
1008         if (data->vma && PMEM_IS_SUBMAP(data)) {
1009                 if (operation == PMEM_MAP)
1010                         ret = pmem_remap_pfn_range(id, data->vma, data,
1011                                                    region->offset, region->len);
1012                 else if (operation == PMEM_UNMAP)
1013                         ret = pmem_unmap_pfn_range(id, data->vma, data,
1014                                                    region->offset, region->len);
1015         }
1016
1017 err:
1018         pmem_unlock_data_and_mm(data, mm);
1019         return ret;
1020 }
1021
1022 static void pmem_revoke(struct file *file, struct pmem_data *data)
1023 {
1024         struct pmem_region_node *region_node;
1025         struct list_head *elt, *elt2;
1026         struct mm_struct *mm = NULL;
1027         int id = get_id(file);
1028         int ret = 0;
1029
1030         data->master_file = NULL;
1031         ret = pmem_lock_data_and_mm(file, data, &mm);
1032         /* if lock_data_and_mm fails either the task that mapped the fd, or
1033          * the vma that mapped it have already gone away, nothing more
1034          * needs to be done */
1035         if (ret)
1036                 return;
1037         /* unmap everything */
1038         /* delete the regions and region list nothing is mapped any more */
1039         if (data->vma)
1040                 list_for_each_safe(elt, elt2, &data->region_list) {
1041                         region_node = list_entry(elt, struct pmem_region_node,
1042                                                  list);
1043                         pmem_unmap_pfn_range(id, data->vma, data,
1044                                              region_node->region.offset,
1045                                              region_node->region.len);
1046                         list_del(elt);
1047                         kfree(region_node);
1048         }
1049         /* delete the master file */
1050         pmem_unlock_data_and_mm(data, mm);
1051 }
1052
1053 static void pmem_get_size(struct pmem_region *region, struct file *file)
1054 {
1055         struct pmem_data *data = (struct pmem_data *)file->private_data;
1056         int id = get_id(file);
1057
1058         if (!has_allocation(file)) {
1059                 region->offset = 0;
1060                 region->len = 0;
1061                 return;
1062         } else {
1063                 region->offset = pmem_start_addr(id, data);
1064                 region->len = pmem_len(id, data);
1065         }
1066         DLOG("offset %lx len %lx\n", region->offset, region->len);
1067 }
1068
1069
1070 static long pmem_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
1071 {
1072         struct pmem_data *data;
1073         int id = get_id(file);
1074
1075         switch (cmd) {
1076         case PMEM_GET_PHYS:
1077                 {
1078                         struct pmem_region region;
1079                         DLOG("get_phys\n");
1080                         if (!has_allocation(file)) {
1081                                 region.offset = 0;
1082                                 region.len = 0;
1083                         } else {
1084                                 data = (struct pmem_data *)file->private_data;
1085                                 region.offset = pmem_start_addr(id, data);
1086                                 region.len = pmem_len(id, data);
1087                         }
1088                         printk(KERN_INFO "pmem: request for physical address of pmem region "
1089                                         "from process %d.\n", current->pid);
1090                         if (copy_to_user((void __user *)arg, &region,
1091                                                 sizeof(struct pmem_region)))
1092                                 return -EFAULT;
1093                         break;
1094                 }
1095         case PMEM_MAP:
1096                 {
1097                         struct pmem_region region;
1098                         if (copy_from_user(&region, (void __user *)arg,
1099                                                 sizeof(struct pmem_region)))
1100                                 return -EFAULT;
1101                         data = (struct pmem_data *)file->private_data;
1102                         return pmem_remap(&region, file, PMEM_MAP);
1103                 }
1104                 break;
1105         case PMEM_UNMAP:
1106                 {
1107                         struct pmem_region region;
1108                         if (copy_from_user(&region, (void __user *)arg,
1109                                                 sizeof(struct pmem_region)))
1110                                 return -EFAULT;
1111                         data = (struct pmem_data *)file->private_data;
1112                         return pmem_remap(&region, file, PMEM_UNMAP);
1113                         break;
1114                 }
1115         case PMEM_GET_SIZE:
1116                 {
1117                         struct pmem_region region;
1118                         DLOG("get_size\n");
1119                         pmem_get_size(&region, file);
1120                         if (copy_to_user((void __user *)arg, &region,
1121                                                 sizeof(struct pmem_region)))
1122                                 return -EFAULT;
1123                         break;
1124                 }
1125         case PMEM_GET_TOTAL_SIZE:
1126                 {
1127                         struct pmem_region region;
1128                         DLOG("get total size\n");
1129                         region.offset = 0;
1130                         get_id(file);
1131                         region.len = pmem[id].size;
1132                         if (copy_to_user((void __user *)arg, &region,
1133                                                 sizeof(struct pmem_region)))
1134                                 return -EFAULT;
1135                         break;
1136                 }
1137         case PMEM_ALLOCATE:
1138                 {
1139                         if (has_allocation(file))
1140                                 return -EINVAL;
1141                         data = (struct pmem_data *)file->private_data;
1142                         data->index = pmem_allocate(id, arg);
1143                         break;
1144                 }
1145         case PMEM_CONNECT:
1146                 DLOG("connect\n");
1147                 return pmem_connect(arg, file);
1148                 break;
1149         default:
1150                 if (pmem[id].ioctl)
1151                         return pmem[id].ioctl(file, cmd, arg);
1152                 return -EINVAL;
1153         }
1154         return 0;
1155 }
1156
1157 #if PMEM_DEBUG
1158 static ssize_t debug_open(struct inode *inode, struct file *file)
1159 {
1160         file->private_data = inode->i_private;
1161         return 0;
1162 }
1163
1164 static ssize_t debug_read(struct file *file, char __user *buf, size_t count,
1165                           loff_t *ppos)
1166 {
1167         struct list_head *elt, *elt2;
1168         struct pmem_data *data;
1169         struct pmem_region_node *region_node;
1170         int id = (int)file->private_data;
1171         const int debug_bufmax = 4096;
1172         static char buffer[4096];
1173         int n = 0;
1174
1175         DLOG("debug open\n");
1176         n = scnprintf(buffer, debug_bufmax,
1177                       "pid #: mapped regions (offset, len) (offset,len)...\n");
1178
1179         down(&pmem[id].data_list_sem);
1180         list_for_each(elt, &pmem[id].data_list) {
1181                 data = list_entry(elt, struct pmem_data, list);
1182                 down_read(&data->sem);
1183                 n += scnprintf(buffer + n, debug_bufmax - n, "pid %u:",
1184                                 data->pid);
1185                 list_for_each(elt2, &data->region_list) {
1186                         region_node = list_entry(elt2, struct pmem_region_node,
1187                                       list);
1188                         n += scnprintf(buffer + n, debug_bufmax - n,
1189                                         "(%lx,%lx) ",
1190                                         region_node->region.offset,
1191                                         region_node->region.len);
1192                 }
1193                 n += scnprintf(buffer + n, debug_bufmax - n, "\n");
1194                 up_read(&data->sem);
1195         }
1196         up(&pmem[id].data_list_sem);
1197
1198         n++;
1199         buffer[n] = 0;
1200         return simple_read_from_buffer(buf, count, ppos, buffer, n);
1201 }
1202
1203 static struct file_operations debug_fops = {
1204         .read = debug_read,
1205         .open = debug_open,
1206 };
1207 #endif
1208
1209 #if 0
1210 static struct miscdevice pmem_dev = {
1211         .name = "pmem",
1212         .fops = &pmem_fops,
1213 };
1214 #endif
1215
1216 int pmem_setup(struct android_pmem_platform_data *pdata,
1217                long (*ioctl)(struct file *, unsigned int, unsigned long),
1218                int (*release)(struct inode *, struct file *))
1219 {
1220         int err = 0;
1221         int i, index = 0;
1222         int id = id_count;
1223         id_count++;
1224
1225         pmem[id].no_allocator = pdata->no_allocator;
1226         pmem[id].cached = pdata->cached;
1227         pmem[id].buffered = pdata->buffered;
1228         pmem[id].base = pdata->start;
1229         pmem[id].size = pdata->size;
1230         pmem[id].ioctl = ioctl;
1231         pmem[id].release = release;
1232         init_rwsem(&pmem[id].bitmap_sem);
1233         init_MUTEX(&pmem[id].data_list_sem);
1234         INIT_LIST_HEAD(&pmem[id].data_list);
1235         pmem[id].dev.name = pdata->name;
1236         pmem[id].dev.minor = id;
1237         pmem[id].dev.fops = &pmem_fops;
1238         printk(KERN_INFO "%s: %d init\n", pdata->name, pdata->cached);
1239
1240         err = misc_register(&pmem[id].dev);
1241         if (err) {
1242                 printk(KERN_ALERT "Unable to register pmem driver!\n");
1243                 goto err_cant_register_device;
1244         }
1245         pmem[id].num_entries = pmem[id].size / PMEM_MIN_ALLOC;
1246
1247         pmem[id].bitmap = kmalloc(pmem[id].num_entries *
1248                                   sizeof(struct pmem_bits), GFP_KERNEL);
1249         if (!pmem[id].bitmap)
1250                 goto err_no_mem_for_metadata;
1251
1252         memset(pmem[id].bitmap, 0, sizeof(struct pmem_bits) *
1253                                           pmem[id].num_entries);
1254
1255         for (i = sizeof(pmem[id].num_entries) * 8 - 1; i >= 0; i--) {
1256                 if ((pmem[id].num_entries) &  1<<i) {
1257                         PMEM_ORDER(id, index) = i;
1258                         index = PMEM_NEXT_INDEX(id, index);
1259                 }
1260         }
1261
1262         if (pmem[id].cached)
1263                 pmem[id].vbase = ioremap_cached(pmem[id].base,
1264                                                 pmem[id].size);
1265 #ifdef ioremap_ext_buffered
1266         else if (pmem[id].buffered)
1267                 pmem[id].vbase = ioremap_ext_buffered(pmem[id].base,
1268                                                       pmem[id].size);
1269 #endif
1270         else
1271                 pmem[id].vbase = ioremap(pmem[id].base, pmem[id].size);
1272
1273         if (pmem[id].vbase == 0)
1274                 goto error_cant_remap;
1275
1276         pmem[id].garbage_pfn = page_to_pfn(alloc_page(GFP_KERNEL));
1277         if (pmem[id].no_allocator)
1278                 pmem[id].allocated = 0;
1279
1280 #if PMEM_DEBUG
1281         debugfs_create_file(pdata->name, S_IFREG | S_IRUGO, NULL, (void *)id,
1282                             &debug_fops);
1283 #endif
1284         return 0;
1285 error_cant_remap:
1286         kfree(pmem[id].bitmap);
1287 err_no_mem_for_metadata:
1288         misc_deregister(&pmem[id].dev);
1289 err_cant_register_device:
1290         return -1;
1291 }
1292
1293 static int pmem_probe(struct platform_device *pdev)
1294 {
1295         struct android_pmem_platform_data *pdata;
1296
1297         if (!pdev || !pdev->dev.platform_data) {
1298                 printk(KERN_ALERT "Unable to probe pmem!\n");
1299                 return -1;
1300         }
1301         pdata = pdev->dev.platform_data;
1302         return pmem_setup(pdata, NULL, NULL);
1303 }
1304
1305
1306 static int pmem_remove(struct platform_device *pdev)
1307 {
1308         int id = pdev->id;
1309         __free_page(pfn_to_page(pmem[id].garbage_pfn));
1310         misc_deregister(&pmem[id].dev);
1311         return 0;
1312 }
1313
1314 static struct platform_driver pmem_driver = {
1315         .probe = pmem_probe,
1316         .remove = pmem_remove,
1317         .driver = { .name = "android_pmem" }
1318 };
1319
1320
1321 static int __init pmem_init(void)
1322 {
1323         return platform_driver_register(&pmem_driver);
1324 }
1325
1326 static void __exit pmem_exit(void)
1327 {
1328         platform_driver_unregister(&pmem_driver);
1329 }
1330
1331 module_init(pmem_init);
1332 module_exit(pmem_exit);
1333