blob: e58e33b32c6686b3dd51c583dc09c90aabac892e [file] [log] [blame]
/* Allocate memory blocks
*
* Copyright (C) 2009 On2 Technologies Finland Oy.
*
* This program 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.
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
--------------------------------------------------------------------------------
--
-- Version control information, please leave untouched.
--
-- $RCSfile: memalloc.c,v $
-- $Date: 2011/03/10 14:03:45 $
-- $Revision: 1.1 $
--
------------------------------------------------------------------------------*/
#include <linux/kernel.h>
#include <linux/module.h>
/* needed for __init,__exit directives */
#include <linux/init.h>
/* needed for remap_page_range */
#include <linux/mm.h>
/* obviously, for kmalloc */
#include <linux/slab.h>
/* for struct file_operations, register_chrdev() */
#include <linux/fs.h>
/* standard error codes */
#include <linux/errno.h>
/* this header files wraps some common module-space operations ...
here we use mem_map_reserve() macro */
#include <asm/io.h>
#include <asm/uaccess.h>
#include <linux/ioport.h>
#include <linux/list.h>
/* for current pid */
#include <linux/sched.h>
/* Our header */
#include "hx280enc.h"
#include "memalloc.h"
/*platform device*/
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
/* module description */
MODULE_LICENSE ("GPL");
MODULE_AUTHOR ("Hantro Products Oy");
MODULE_DESCRIPTION ("RAM allocation");
#define MAXDEV 2 //ENCODE and DECODER
#define MEMALLOC_SW_MINOR 6
#define MEMALLOC_SW_MAJOR 0
#define MEMALLOC_SW_BUILD ((MEMALLOC_SW_MAJOR * 1000) + MEMALLOC_SW_MINOR)
static void __exit
memalloc_cleanup (void)
{
printk (KERN_INFO "memalloc: module removed\n");
return;
}
/*We must keep a list of the allocated chunk*/
int
memalloc_AllocMemory (struct device *dev, hlinc *chunks,unsigned *busaddr, unsigned int size)
{
int err;
void *rslt;
unsigned int asked_page;
hlinc *elem;
if (!size)
{
err = -1;
goto out;
}
asked_page = PAGE_ALIGN (size);
rslt =
(unsigned *) dma_alloc_coherent (dev, asked_page,
(dma_addr_t *) busaddr, GFP_DMA);
if (!rslt)
{
PDEBUG ("MEMALLOC FAILED: size = %d\n", size);
goto out;
}
PDEBUG (KERN_WARNING
"MEMALLOC OK: size: %d, size reserved: %d at @ 0x%x\n", size,
asked_page, *busaddr);
elem = kmalloc (sizeof *chunks, GFP_KERNEL);
PDEBUG (KERN_WARNING "alloc %d\n", asked_page);
elem->bus_address = *busaddr;
elem->size = asked_page;
elem->ba = rslt;
list_add (&(elem->list), &(chunks->list));
return 0;
out:
return err;
}
EXPORT_SYMBOL (memalloc_AllocMemory);
void
memalloc_FreeMemory (struct device *dev, hlinc *chunks,unsigned long busaddr)
{
hlinc *res, *resn;
list_for_each_entry_safe (res, resn, &(chunks->list), list)
{
PDEBUG (KERN_INFO "elem 0x%x, curr 0x%x\n", res->bus_address,
(unsigned int) busaddr);
if (res->bus_address == busaddr)
{
PDEBUG (KERN_WARNING "alloc - 1 %d\n", res->size);
dma_free_coherent (dev, res->size, (void *) res->ba,
res->bus_address);
list_del (&res->list);
kfree (res);
break;
}
}
}
EXPORT_SYMBOL (memalloc_FreeMemory);
void
memalloc_ResetMems (struct device *dev, hlinc *chunks)
{
hlinc *res, *resn;
list_for_each_entry_safe (res, resn, &(chunks->list), list)
{
dma_free_coherent (dev, res->size, (void *) res->ba, res->bus_address);
list_del (&res->list);
kfree (res);
}
}
EXPORT_SYMBOL (memalloc_ResetMems);
int
memalloc_register(struct device *dev, hlinc *chunks, dma_addr_t bus_addr, unsigned int size)
{
int err;
INIT_LIST_HEAD (&(chunks->list));
err =
dma_declare_coherent_memory (dev, bus_addr, bus_addr,
size, DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE);
if (!err)
{
return -ENOMEM;
}
return 0;
}
EXPORT_SYMBOL (memalloc_register);
int
memalloc_unregister (struct device *dev)
{
dma_release_declared_memory (dev);
return 0;
}
EXPORT_SYMBOL (memalloc_unregister);
int __init
memalloc_init (void)
{
return 0;
}
module_init (memalloc_init);
module_exit (memalloc_cleanup);