aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/ubicom32/files/arch/ubicom32/mm/ocm-alloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/ubicom32/files/arch/ubicom32/mm/ocm-alloc.c')
-rw-r--r--target/linux/ubicom32/files/arch/ubicom32/mm/ocm-alloc.c487
1 files changed, 0 insertions, 487 deletions
diff --git a/target/linux/ubicom32/files/arch/ubicom32/mm/ocm-alloc.c b/target/linux/ubicom32/files/arch/ubicom32/mm/ocm-alloc.c
deleted file mode 100644
index 5a10c2938b..0000000000
--- a/target/linux/ubicom32/files/arch/ubicom32/mm/ocm-alloc.c
+++ /dev/null
@@ -1,487 +0,0 @@
-/*
- * arch/ubicom32/mm/ocm-alloc.c
- * OCM allocator for Uibcom32 On-Chip memory
- *
- * (C) Copyright 2009, Ubicom, Inc.
- * Copyright 2004-2008 Analog Devices Inc.
- *
- * Based on:
- *
- * arch/blackfin/mm/sram-alloc.c
- *
- *
- * This file is part of the Ubicom32 Linux Kernel Port.
- *
- * The Ubicom32 Linux Kernel Port is free software: you can redistribute
- * it and/or modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation, either version 2 of the
- * License, or (at your option) any later version.
- *
- * The Ubicom32 Linux Kernel Port is distributed in the hope that it
- * will be useful, but WITHOUT ANY WARRANTY; without even the implied
- * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
- * the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with the Ubicom32 Linux Kernel Port. If not,
- * see <http://www.gnu.org/licenses/>.
- *
- * Ubicom32 implementation derived from (with many thanks):
- * arch/m68knommu
- * arch/blackfin
- * arch/parisc
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/miscdevice.h>
-#include <linux/ioport.h>
-#include <linux/fcntl.h>
-#include <linux/init.h>
-#include <linux/poll.h>
-#include <linux/proc_fs.h>
-#include <linux/mutex.h>
-#include <linux/rtc.h>
-#include <asm/ocm-alloc.h>
-
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(fmt, a...)
-#endif
-/*
- * the data structure for OCM heap pieces
- */
-struct ocm_piece {
- void *paddr;
- int size;
- pid_t pid;
- struct ocm_piece *next;
-};
-
-/*
- * struct ocm_heap
- */
-struct ocm_heap {
- struct ocm_piece free_head;
- struct ocm_piece used_head;
- struct mutex lock;
-};
-
-static struct ocm_heap ocm_inst_heap;
-int ubi32_ocm_skbuf_max = 21, ubi32_ocm_skbuf, ubi32_ddr_skbuf;
-
-/*
- * OCM area for storing code
- */
-extern asmlinkage void *__ocm_free_begin;
-extern asmlinkage void *__ocm_free_end;
-extern asmlinkage void *__ocm_inst_heap_begin;
-extern asmlinkage void *__ocm_inst_heap_end;
-#define OCM_INST_HEAP_BEGIN ((unsigned int)&__ocm_inst_heap_begin)
-#define OCM_INST_HEAP_END ((unsigned int)&__ocm_inst_heap_end)
-#define OCM_INST_HEAP_LENGTH (OCM_INST_HEAP_END - OCM_INST_HEAP_BEGIN)
-
-static struct kmem_cache *ocm_piece_cache;
-
-/*
- * _ocm_heap_init()
- */
-static int __init _ocm_heap_init(struct ocm_heap *ocmh,
- unsigned int start,
- unsigned int size)
-{
- ocmh->free_head.next = kmem_cache_alloc(ocm_piece_cache, GFP_KERNEL);
-
- if (!ocmh->free_head.next)
- return -1;
-
- ocmh->free_head.next->paddr = (void *)start;
- ocmh->free_head.next->size = size;
- ocmh->free_head.next->pid = 0;
- ocmh->free_head.next->next = 0;
-
- ocmh->used_head.next = NULL;
-
- /* mutex initialize */
- mutex_init(&ocmh->lock);
-
- return 0;
-}
-
-/*
- * _ocm_alloc_init()
- *
- * starts the ocm heap(s)
- */
-static int __init _ocm_alloc_init(void)
-{
- if (OCM_INST_HEAP_LENGTH) {
- ocm_piece_cache = kmem_cache_create("ocm_piece_cache",
- sizeof(struct ocm_piece),
- 0, SLAB_PANIC, NULL);
-
- if (_ocm_heap_init(&ocm_inst_heap,
- OCM_INST_HEAP_BEGIN,
- OCM_INST_HEAP_LENGTH) == 0)
- printk(KERN_INFO "OCM Instruction Heap %d KB\n",
- OCM_INST_HEAP_LENGTH >> 10);
- else
- printk(KERN_INFO "Failed to initialize OCM "
- "Instruction Heap\n");
-
- } else
- printk(KERN_INFO "No space available for OCM "
- "Instruction Heap\n");
-
- return 0;
-}
-pure_initcall(_ocm_alloc_init);
-
-/*
- * _ocm_alloc()
- * generic alloc a block in the ocm heap, if successful
- * returns the pointer.
- */
-static void *_ocm_alloc(size_t size, pid_t pid, struct ocm_heap *ocmheap)
-{
- struct ocm_piece *pslot, *plast, *pavail;
- struct ocm_piece *pfree_head = &ocmheap->free_head;
- struct ocm_piece *pused_head = &ocmheap->used_head;
-
- if (size <= 0 || !pfree_head || !pused_head)
- return NULL;
-
- /* Align the size */
- size = (size + 3) & ~3;
-
- pslot = pfree_head->next;
- plast = pfree_head;
-
- /*
- * search an available piece slot
- */
- while (pslot != NULL && size > pslot->size) {
- plast = pslot;
- pslot = pslot->next;
- }
-
- if (!pslot)
- return NULL;
-
- if (pslot->size == size) {
- /*
- * Unlink this block from the list
- */
- plast->next = pslot->next;
- pavail = pslot;
- } else {
- /*
- * Split this block in two.
- */
- pavail = kmem_cache_alloc(ocm_piece_cache, GFP_KERNEL);
-
- if (!pavail)
- return NULL;
-
- pavail->paddr = pslot->paddr;
- pavail->size = size;
- pslot->paddr += size;
- pslot->size -= size;
- }
-
- pavail->pid = pid;
-
- pslot = pused_head->next;
- plast = pused_head;
-
- /*
- * insert new piece into used piece list !!!
- */
- while (pslot != NULL && pavail->paddr < pslot->paddr) {
- plast = pslot;
- pslot = pslot->next;
- }
-
- pavail->next = pslot;
- plast->next = pavail;
-
- DEBUGP("_ocm_alloc %d bytes at %p from in %p",
- size, pavail->paddr, ocmheap);
-
- return pavail->paddr;
-}
-
-#if 0
-/* Allocate the largest available block. */
-static void *_ocm_alloc_max(struct ocm_heap *ocmheap,
- unsigned long *psize)
-{
- struct ocm_piece *pfree_head = &ocmheap->free_head;
- struct ocm_piece *pslot, *pmax;
-
- pmax = pslot = pfree_head->next;
-
- /* search an available piece slot */
- while (pslot != NULL) {
- if (pslot->size > pmax->size)
- pmax = pslot;
- pslot = pslot->next;
- }
-
- if (!pmax)
- return NULL;
-
- *psize = pmax->size;
-
- return _ocm_alloc(*psize, ocmheap);
-}
-#endif
-
-/*
- * _ocm_free()
- * generic free a block in the ocm heap, if successful
- */
-static int _ocm_free(const void *addr,
- struct ocm_heap *ocmheap)
-{
- struct ocm_piece *pslot, *plast, *pavail;
- struct ocm_piece *pfree_head = &ocmheap->free_head;
- struct ocm_piece *pused_head = &ocmheap->used_head;
-
- /* search the relevant memory slot */
- pslot = pused_head->next;
- plast = pused_head;
-
- /* search an available piece slot */
- while (pslot != NULL && pslot->paddr != addr) {
- plast = pslot;
- pslot = pslot->next;
- }
-
- if (!pslot) {
- DEBUGP("_ocm_free %p not found in %p", addr, ocmheap);
- return -1;
- }
- DEBUGP("_ocm_free %p from in %p", addr, ocmheap);
-
- plast->next = pslot->next;
- pavail = pslot;
- pavail->pid = 0;
-
- /* insert free pieces back to the free list */
- pslot = pfree_head->next;
- plast = pfree_head;
-
- while (pslot != NULL && addr > pslot->paddr) {
- plast = pslot;
- pslot = pslot->next;
- }
-
- if (plast != pfree_head &&
- plast->paddr + plast->size == pavail->paddr) {
- plast->size += pavail->size;
- kmem_cache_free(ocm_piece_cache, pavail);
- } else {
- pavail->next = plast->next;
- plast->next = pavail;
- plast = pavail;
- }
-
- if (pslot && plast->paddr + plast->size == pslot->paddr) {
- plast->size += pslot->size;
- plast->next = pslot->next;
- kmem_cache_free(ocm_piece_cache, pslot);
- }
-
- return 0;
-}
-
-/*
- * ocm_inst_alloc()
- *
- * allocates a block of size in the ocm instrction heap, if
- * successful returns address allocated.
- */
-void *ocm_inst_alloc(size_t size, pid_t pid)
-{
- void *addr;
-
- if (!OCM_INST_HEAP_LENGTH)
- return NULL;
-
-
- mutex_lock(&ocm_inst_heap.lock);
-
- addr = _ocm_alloc(size, pid, &ocm_inst_heap);
-
- mutex_unlock(&ocm_inst_heap.lock);
-
- return addr;
-}
-EXPORT_SYMBOL(ocm_inst_alloc);
-
-/*
- * ocm_inst_free()
- * free a block in the ocm instrction heap, returns 0 if successful.
- */
-int ocm_inst_free(const void *addr)
-{
- int ret;
-
- if (!OCM_INST_HEAP_LENGTH)
- return -1;
-
- mutex_lock(&ocm_inst_heap.lock);
-
- ret = _ocm_free(addr, &ocm_inst_heap);
-
- mutex_unlock(&ocm_inst_heap.lock);
-
- return ret;
-}
-EXPORT_SYMBOL(ocm_inst_free);
-
-/*
- * ocm_free()
- * free a block in one of the ocm heaps, returns 0 if successful.
- */
-int ocm_free(const void *addr)
-{
- if (addr >= (void *)OCM_INST_HEAP_BEGIN
- && addr < (void *)(OCM_INST_HEAP_END))
- return ocm_inst_free(addr);
- else
- return -1;
-}
-EXPORT_SYMBOL(ocm_free);
-
-
-#ifdef CONFIG_PROC_FS
-/* Need to keep line of output the same. Currently, that is 46 bytes
- * (including newline).
- */
-static int _ocm_proc_read(char *buf, int *len, int count, const char *desc,
- struct ocm_heap *ocmheap)
-{
- struct ocm_piece *pslot;
- struct ocm_piece *pfree_head = &ocmheap->free_head;
- struct ocm_piece *pused_head = &ocmheap->used_head;
-
- /* The format is the following
- * --- OCM 123456789012345 Size PID State \n
- * 12345678-12345678 1234567890 12345 1234567890\n
- */
- int l;
- l = sprintf(&buf[*len], "--- OCM %-15s Size PID State \n",
- desc);
-
- *len += l;
- count -= l;
-
- mutex_lock(&ocm_inst_heap.lock);
-
- /*
- * search the relevant memory slot
- */
- pslot = pused_head->next;
-
- while (pslot != NULL && count > 46) {
- l = sprintf(&buf[*len], "%p-%p %10i %5i %-10s\n",
- pslot->paddr, pslot->paddr + pslot->size,
- pslot->size, pslot->pid, "ALLOCATED");
-
- *len += l;
- count -= l;
- pslot = pslot->next;
- }
-
- pslot = pfree_head->next;
-
- while (pslot != NULL && count > 46) {
- l = sprintf(&buf[*len], "%p-%p %10i %5i %-10s\n",
- pslot->paddr, pslot->paddr + pslot->size,
- pslot->size, pslot->pid, "FREE");
-
- *len += l;
- count -= l;
- pslot = pslot->next;
- }
-
- mutex_unlock(&ocm_inst_heap.lock);
-
- return 0;
-}
-
-static int ocm_proc_read(char *buf, char **start, off_t offset, int count,
- int *eof, void *data)
-{
- int len = 0;
-
- len = sprintf(&buf[len], "--- OCM SKB usage (max RX buf %d)\n"
- "(SKB in OCM) %d - (SKB in DDR) %d\n",
- ubi32_ocm_skbuf_max,
- ubi32_ocm_skbuf,
- ubi32_ddr_skbuf);
-
- len += sprintf(&buf[len], "--- OCM Data Heap Size\n"
- "%p-%p %10i\n",
- ((void *)&__ocm_free_begin),
- ((void *)&__ocm_free_end),
- ((unsigned int)&__ocm_free_end) -
- ((unsigned int)&__ocm_free_begin));
-
- if (_ocm_proc_read(buf, &len, count - len, "Inst Heap",
- &ocm_inst_heap))
- goto not_done;
- *eof = 1;
- not_done:
- return len;
-}
-
-static int ocm_proc_write(struct file *file, const char __user *buffer,
- unsigned long count, void *data)
-{
- int n, v;
- char in[8];
-
- if (count > sizeof(in))
- return -EINVAL;
-
- if (copy_from_user(in, buffer, count))
- return -EFAULT;
- in[count-1] = 0;
-
- printk(KERN_INFO "OCM skb alloc max = %s\n", in);
-
- n = 0;
- v = 0;
- while ((in[n] >= '0') && (in[n] <= '9')) {
- v = v * 10 + (int)(in[n] - '0');
- n++;
- }
-
- if (v == 0)
- return -EINVAL;
-
- ubi32_ocm_skbuf_max = v;
- ubi32_ocm_skbuf = ubi32_ddr_skbuf = 0;
-
- return count;
-}
-
-static int __init sram_proc_init(void)
-{
- struct proc_dir_entry *ptr;
- ptr = create_proc_entry("ocm", S_IFREG | S_IRUGO, NULL);
- if (!ptr) {
- printk(KERN_WARNING "unable to create /proc/ocm\n");
- return -1;
- }
- ptr->read_proc = ocm_proc_read;
- ptr->write_proc = ocm_proc_write;
- return 0;
-}
-late_initcall(sram_proc_init);
-#endif