GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
ifneq ($(srctree),)
|
||||
KERNEL_DIR := $(srctree)
|
||||
SDK_DIR := $(shell cd $(KERNEL_DIR)/../../.. && /bin/pwd)
|
||||
else
|
||||
SDK_DIR := $(shell cd $(CURDIR)/../../../../../.. && /bin/pwd)
|
||||
endif
|
||||
|
||||
include $(SDK_DIR)/build/base.mk
|
||||
include $(SDK_DIR)/build/version.mk
|
||||
|
||||
OSAL_ROOT := $(GMP_DIR)/drv/osal
|
||||
|
||||
MOD_NAME := xm_osal
|
||||
|
||||
SRCS := osal_fileops.c \
|
||||
osal_vmalloc.c \
|
||||
osal_addr.c \
|
||||
osal_init.c \
|
||||
osal_atomic.c \
|
||||
osal_barrier.c \
|
||||
osal_cache.c \
|
||||
osal_debug.c \
|
||||
osal_device.c \
|
||||
osal_interrupt.c \
|
||||
osal_math.c \
|
||||
osal_mutex.c \
|
||||
osal_proc.c \
|
||||
osal_schedule.c \
|
||||
osal_semaphore.c \
|
||||
osal_spinlock.c \
|
||||
osal_string.c \
|
||||
osal_task.c \
|
||||
osal_timer.c \
|
||||
osal_wait.c \
|
||||
osal_workqueue.c \
|
||||
osal_notifier.c \
|
||||
osal_platform.c
|
||||
|
||||
SRCS += ./media/base.c \
|
||||
./media/media.c \
|
||||
./mmz/media-mem.c \
|
||||
./mmz/mmz-userdev.c \
|
||||
./mmz/drv_mmz.c \
|
||||
./mmz/allocator.c
|
||||
|
||||
ifeq ($(CONFIG_CMA),y)
|
||||
SRCS += ./mmz/cma_allocator.c
|
||||
endif
|
||||
|
||||
SDK_KER_CFLAGS += -D$(CHIPSET) -DRELEASE -DUSER_BIT_32 -DKERNEL_BIT_32 -Wno-date-time -D_GNU_SOURCE
|
||||
|
||||
SDK_KER_CFLAGS += -I$(OSAL_ROOT)/include \
|
||||
-I$(OSAL_ROOT)/linux/kernel \
|
||||
-I$(OSAL_ROOT)/linux/kernel/media \
|
||||
-I$(OSAL_ROOT)/linux/kernel/mmz \
|
||||
-I$(GMP_DIR)/drv/include \
|
||||
-I$(GMP_DIR)/include
|
||||
|
||||
include $(SDK_DIR)/build/sdk_ko_rules.mk
|
||||
+362
@@ -0,0 +1,362 @@
|
||||
/*
|
||||
* Copyright (c) XMEDIA. All rights reserved.
|
||||
*/
|
||||
#include <linux/version.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/major.h>
|
||||
#include <linux/stat.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kmod.h>
|
||||
|
||||
#include "base.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
/**** media bus ****/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void media_bus_release(struct device *dev)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
struct device media_bus = {
|
||||
// change media_bus name from "media" to "gmp", because bus "media" is used in kenrel
|
||||
.init_name = "gmp",
|
||||
.release = media_bus_release
|
||||
};
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0)
|
||||
/* sysfs modalias store/show */
|
||||
static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
|
||||
char *buf)
|
||||
{
|
||||
struct media_device *pdev = to_media_device(dev);
|
||||
int len = snprintf(buf, PAGE_SIZE, "media:%s\n", pdev->devfs_name);
|
||||
|
||||
return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
|
||||
}
|
||||
|
||||
static struct device_attribute media_dev_attrs[] = {
|
||||
__ATTR_RO(modalias),
|
||||
__ATTR_NULL,
|
||||
};
|
||||
#endif
|
||||
|
||||
/* bus match & uevent */
|
||||
static int media_match(struct device *dev, struct device_driver *drv)
|
||||
{
|
||||
struct media_device *pdev = to_media_device(dev);
|
||||
return (strncmp(pdev->devfs_name, drv->name, sizeof(pdev->devfs_name)) == 0);
|
||||
}
|
||||
|
||||
static int media_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||
{
|
||||
struct media_device *pdev = to_media_device(dev);
|
||||
add_uevent_var(env, "MODALIAS=media:%s", pdev->devfs_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
// pm methods
|
||||
static int media_pm_prepare(struct device *dev)
|
||||
{
|
||||
struct media_device *pdev = to_media_device(dev);
|
||||
struct media_driver *pdrv = to_media_driver(dev->driver);
|
||||
|
||||
if ((pdrv->ops == NULL) || (pdrv->ops->pm_prepare == NULL)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return pdrv->ops->pm_prepare(pdev);
|
||||
}
|
||||
|
||||
static void media_pm_complete(struct device *dev)
|
||||
{
|
||||
struct media_device *pdev = to_media_device(dev);
|
||||
struct media_driver *pdrv = to_media_driver(dev->driver);
|
||||
|
||||
if ((pdrv->ops == NULL) || (pdrv->ops->pm_complete == NULL)) {
|
||||
return;
|
||||
}
|
||||
|
||||
pdrv->ops->pm_complete(pdev);
|
||||
}
|
||||
|
||||
static int media_pm_suspend(struct device *dev)
|
||||
{
|
||||
struct media_device *pdev = to_media_device(dev);
|
||||
struct media_driver *pdrv = to_media_driver(dev->driver);
|
||||
|
||||
if ((pdrv->ops == NULL) || (pdrv->ops->pm_suspend == NULL)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return pdrv->ops->pm_suspend(pdev);
|
||||
}
|
||||
|
||||
static int media_pm_resume(struct device *dev)
|
||||
{
|
||||
struct media_device *pdev = to_media_device(dev);
|
||||
struct media_driver *pdrv = to_media_driver(dev->driver);
|
||||
|
||||
if ((pdrv->ops == NULL) || (pdrv->ops->pm_resume == NULL)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return pdrv->ops->pm_resume(pdev);
|
||||
}
|
||||
|
||||
static int media_pm_freeze(struct device *dev)
|
||||
{
|
||||
struct media_device *pdev = to_media_device(dev);
|
||||
struct media_driver *pdrv = to_media_driver(dev->driver);
|
||||
|
||||
if ((pdrv->ops == NULL) || (pdrv->ops->pm_freeze == NULL)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return pdrv->ops->pm_freeze(pdev);
|
||||
}
|
||||
|
||||
static int media_pm_thaw(struct device *dev)
|
||||
{
|
||||
struct media_device *pdev = to_media_device(dev);
|
||||
struct media_driver *pdrv = to_media_driver(dev->driver);
|
||||
|
||||
if ((pdrv->ops == NULL) || (pdrv->ops->pm_thaw == NULL)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return pdrv->ops->pm_thaw(pdev);
|
||||
}
|
||||
|
||||
static int media_pm_poweroff(struct device *dev)
|
||||
{
|
||||
struct media_device *pdev = to_media_device(dev);
|
||||
struct media_driver *pdrv = to_media_driver(dev->driver);
|
||||
|
||||
if ((pdrv->ops == NULL) || (pdrv->ops->pm_poweroff == NULL)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return pdrv->ops->pm_poweroff(pdev);
|
||||
}
|
||||
|
||||
static int media_pm_restore(struct device *dev)
|
||||
{
|
||||
struct media_device *pdev = to_media_device(dev);
|
||||
struct media_driver *pdrv = to_media_driver(dev->driver);
|
||||
|
||||
if ((pdrv->ops == NULL) || (pdrv->ops->pm_restore == NULL)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return pdrv->ops->pm_restore(pdev);
|
||||
}
|
||||
static int media_pm_suspend_noirq(struct device *dev)
|
||||
{
|
||||
struct media_device *pdev = to_media_device(dev);
|
||||
struct media_driver *pdrv = to_media_driver(dev->driver);
|
||||
|
||||
if ((pdrv->ops == NULL) || (pdrv->ops->pm_suspend_noirq == NULL)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return pdrv->ops->pm_suspend_noirq(pdev);
|
||||
}
|
||||
|
||||
static int media_pm_resume_noirq(struct device *dev)
|
||||
{
|
||||
struct media_device *pdev = to_media_device(dev);
|
||||
struct media_driver *pdrv = to_media_driver(dev->driver);
|
||||
|
||||
if ((pdrv->ops == NULL) || (pdrv->ops->pm_resume_noirq == NULL)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return pdrv->ops->pm_resume_noirq(pdev);
|
||||
}
|
||||
|
||||
static int media_pm_freeze_noirq(struct device *dev)
|
||||
{
|
||||
struct media_device *pdev = to_media_device(dev);
|
||||
struct media_driver *pdrv = to_media_driver(dev->driver);
|
||||
|
||||
if ((pdrv->ops == NULL) || (pdrv->ops->pm_freeze_noirq == NULL)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return pdrv->ops->pm_freeze_noirq(pdev);
|
||||
}
|
||||
|
||||
static int media_pm_thaw_noirq(struct device *dev)
|
||||
{
|
||||
struct media_device *pdev = to_media_device(dev);
|
||||
struct media_driver *pdrv = to_media_driver(dev->driver);
|
||||
|
||||
if ((pdrv->ops == NULL) || (pdrv->ops->pm_thaw_noirq == NULL)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return pdrv->ops->pm_thaw_noirq(pdev);
|
||||
}
|
||||
|
||||
static int media_pm_poweroff_noirq(struct device *dev)
|
||||
{
|
||||
struct media_device *pdev = to_media_device(dev);
|
||||
struct media_driver *pdrv = to_media_driver(dev->driver);
|
||||
|
||||
if ((pdrv->ops == NULL) || (pdrv->ops->pm_poweroff_noirq == NULL)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return pdrv->ops->pm_poweroff_noirq(pdev);
|
||||
}
|
||||
|
||||
static int media_pm_restore_noirq(struct device *dev)
|
||||
{
|
||||
struct media_device *pdev = to_media_device(dev);
|
||||
struct media_driver *pdrv = to_media_driver(dev->driver);
|
||||
|
||||
if ((pdrv->ops == NULL) || (pdrv->ops->pm_restore_noirq == NULL)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return pdrv->ops->pm_restore_noirq(pdev);
|
||||
}
|
||||
|
||||
static struct dev_pm_ops media_bus_pm_ops = {
|
||||
.prepare = media_pm_prepare,
|
||||
.complete = media_pm_complete,
|
||||
|
||||
// with irq
|
||||
.suspend = media_pm_suspend,
|
||||
.resume = media_pm_resume,
|
||||
|
||||
.freeze = media_pm_freeze,
|
||||
.thaw = media_pm_thaw,
|
||||
.poweroff = media_pm_poweroff,
|
||||
.restore = media_pm_restore,
|
||||
|
||||
// with noirq
|
||||
.suspend_noirq = media_pm_suspend_noirq,
|
||||
.resume_noirq = media_pm_resume_noirq,
|
||||
.freeze_noirq = media_pm_freeze_noirq,
|
||||
.thaw_noirq = media_pm_thaw_noirq,
|
||||
.poweroff_noirq = media_pm_poweroff_noirq,
|
||||
.restore_noirq = media_pm_restore_noirq,
|
||||
};
|
||||
|
||||
struct bus_type media_bus_type = {
|
||||
// change media_bus name from "media" to "gmp", because bus "media" is used in kenrel
|
||||
.name = "gmp",
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0)
|
||||
.dev_attrs = media_dev_attrs,
|
||||
#endif
|
||||
.match = media_match,
|
||||
.uevent = media_uevent,
|
||||
.pm = &media_bus_pm_ops,
|
||||
};
|
||||
|
||||
int media_bus_init(void)
|
||||
{
|
||||
int ret;
|
||||
ret = device_register(&media_bus);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = bus_register(&media_bus_type);
|
||||
if (ret) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
error:
|
||||
|
||||
device_unregister(&media_bus);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void media_bus_exit(void)
|
||||
{
|
||||
bus_unregister(&media_bus_type);
|
||||
device_unregister(&media_bus);
|
||||
}
|
||||
|
||||
static void media_device_release(struct device *dev)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int _media_device_register(struct media_device *pdev)
|
||||
{
|
||||
dev_set_name(&pdev->device, "%s", pdev->devfs_name);
|
||||
|
||||
pdev->device.devt = MKDEV(MEDIA_DEVICE_MAJOR, pdev->minor);
|
||||
pdev->device.release = media_device_release;
|
||||
pdev->device.bus = &media_bus_type;
|
||||
|
||||
return device_register(&pdev->device);
|
||||
}
|
||||
|
||||
void _media_device_unregister(struct media_device *pdev)
|
||||
{
|
||||
device_unregister(&pdev->device);
|
||||
}
|
||||
|
||||
struct media_driver *media_driver_register(const char *name,
|
||||
struct module *owner, struct media_ops *ops)
|
||||
{
|
||||
int ret;
|
||||
struct media_driver *pdrv = NULL;
|
||||
#ifdef MODULE
|
||||
if ((name == NULL) || (owner == NULL)) {
|
||||
#else
|
||||
if (name == NULL){
|
||||
#endif
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
pdrv = kzalloc(sizeof(struct media_driver) + strnlen(name, MEDIA_MAX_DEV_NAME_LEN), GFP_KERNEL);
|
||||
if (pdrv == NULL) {
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
/* init driver object */
|
||||
strncpy(pdrv->name, name, strnlen(name, MEDIA_MAX_DEV_NAME_LEN));
|
||||
|
||||
pdrv->ops = ops;
|
||||
|
||||
pdrv->driver.name = pdrv->name;
|
||||
pdrv->driver.owner = owner;
|
||||
pdrv->driver.bus = &media_bus_type;
|
||||
|
||||
ret = driver_register(&pdrv->driver);
|
||||
if (ret) {
|
||||
kfree(pdrv);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
return pdrv;
|
||||
}
|
||||
|
||||
void media_driver_unregister(struct media_driver *pdrv)
|
||||
{
|
||||
if (pdrv != NULL) {
|
||||
driver_unregister(&pdrv->driver);
|
||||
kfree(pdrv);
|
||||
}
|
||||
}
|
||||
|
||||
// end!
|
||||
/*****************************************************************************/
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) XMEDIA. All rights reserved.
|
||||
*/
|
||||
#ifndef _MEDIA_BASE_H_
|
||||
#define _MEDIA_BASE_H_
|
||||
|
||||
#include "media.h"
|
||||
|
||||
int media_bus_init(void);
|
||||
void media_bus_exit(void);
|
||||
|
||||
#if 0
|
||||
struct device *_media_device_register(struct class *class,
|
||||
dev_t devt, const char *name);
|
||||
|
||||
void _media_device_unregister(struct class *class, dev_t devt);
|
||||
|
||||
#else
|
||||
|
||||
int _media_device_register(struct media_device *pdev);
|
||||
|
||||
void _media_device_unregister(struct media_device *pdev);
|
||||
|
||||
#endif
|
||||
|
||||
struct media_driver *media_driver_register(const char *name,
|
||||
struct module *owner, struct media_ops *ops);
|
||||
|
||||
void media_driver_unregister(struct media_driver *pdrv);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,343 @@
|
||||
/*
|
||||
* Copyright (c) XMEDIA. All rights reserved.
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/major.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/stat.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/kmod.h>
|
||||
#include <linux/devfreq.h>
|
||||
|
||||
#include "base.h"
|
||||
#include "osal_devfreq.h"
|
||||
|
||||
static OSAL_LIST_HEAD(media_list);
|
||||
static DEFINE_MUTEX(media_sem);
|
||||
|
||||
/*
|
||||
* Assigned numbers, used for dynamic minors
|
||||
*/
|
||||
#define DYNAMIC_MINORS 64 /* like dynamic majors */
|
||||
static unsigned char media_minors[DYNAMIC_MINORS / 8];
|
||||
|
||||
int media_devfreq_target(struct device *dev, unsigned long *freq, unsigned int flags)
|
||||
{
|
||||
struct media_device *pdev = to_media_device(dev);
|
||||
struct media_driver *pdrv = to_media_driver(dev->driver);
|
||||
|
||||
if ((pdrv->ops == NULL) || (pdrv->ops->devfreq_target == NULL)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return pdrv->ops->devfreq_target(pdev, freq, flags);
|
||||
}
|
||||
|
||||
int media_devfreq_get_dev_status(struct device *dev, struct devfreq_dev_status *stat)
|
||||
{
|
||||
struct media_device *pdev = to_media_device(dev);
|
||||
struct media_driver *pdrv = to_media_driver(dev->driver);
|
||||
osal_devfreq_dev_status_t pstat;
|
||||
|
||||
if ((pdrv->ops == NULL) || (pdrv->ops->devfreq_get_dev_status == NULL)) {
|
||||
return 0;
|
||||
}
|
||||
pstat.total_time = stat->total_time;
|
||||
pstat.busy_time = stat->busy_time;
|
||||
pstat.current_frequency = stat->current_frequency;
|
||||
pstat.private_data = stat->private_data;
|
||||
|
||||
return pdrv->ops->devfreq_get_dev_status(pdev, &pstat);
|
||||
}
|
||||
|
||||
int media_devfreq_get_cur_freq(struct device *dev, unsigned long *freq)
|
||||
{
|
||||
struct media_device *pdev = to_media_device(dev);
|
||||
struct media_driver *pdrv = to_media_driver(dev->driver);
|
||||
|
||||
if ((pdrv->ops == NULL) || (pdrv->ops->devfreq_get_cur_freq == NULL)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return pdrv->ops->devfreq_get_cur_freq(pdev, freq);
|
||||
}
|
||||
|
||||
void media_devfreq_exit(struct device *dev)
|
||||
{
|
||||
struct media_device *pdev = to_media_device(dev);
|
||||
struct media_driver *pdrv = to_media_driver(dev->driver);
|
||||
|
||||
if ((pdrv->ops == NULL) || (pdrv->ops->devfreq_exit == NULL)) {
|
||||
return;
|
||||
}
|
||||
|
||||
return pdrv->ops->devfreq_exit(pdev);
|
||||
}
|
||||
|
||||
int media_devfreq_register(struct media_device *media, osal_devfreq_para_t *devfreq_para)
|
||||
{
|
||||
struct device *dev = (struct device *)&media->device;
|
||||
struct devfreq_dev_profile *profile = &(media->profile);
|
||||
|
||||
profile->initial_freq = devfreq_para->initial_freq;
|
||||
profile->polling_ms = devfreq_para->polling_ms;
|
||||
profile->target = media_devfreq_target;
|
||||
profile->get_dev_status = media_devfreq_get_dev_status;
|
||||
profile->get_cur_freq = media_devfreq_get_cur_freq;
|
||||
profile->exit = media_devfreq_exit;
|
||||
profile->freq_table = devfreq_para->freq_table;
|
||||
profile->max_state = devfreq_para->max_state;
|
||||
|
||||
media->devfreq = devm_devfreq_add_device(dev, profile, "userspace", NULL);
|
||||
if (IS_ERR(media->devfreq)) {
|
||||
printk("failed to add devfreq device\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void media_devfreq_unregister(struct media_device *media)
|
||||
{
|
||||
struct device *dev = (struct device *)&media->device;
|
||||
|
||||
devm_devfreq_remove_device(dev, media->devfreq);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static int media_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
int minor = iminor(inode);
|
||||
struct media_device *c = NULL;
|
||||
int err = -ENODEV;
|
||||
const struct file_operations *old_fops, *new_fops = NULL;
|
||||
|
||||
mutex_lock(&media_sem);
|
||||
|
||||
osal_list_for_each_entry(c, &media_list, list) {
|
||||
if (c->minor == minor) {
|
||||
new_fops = fops_get(c->fops);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (new_fops == NULL) {
|
||||
mutex_unlock(&media_sem);
|
||||
request_module("char-major-%d-%d", MEDIA_DEVICE_MAJOR, minor);
|
||||
mutex_lock(&media_sem);
|
||||
|
||||
osal_list_for_each_entry(c, &media_list, list) {
|
||||
if (c->minor == minor) {
|
||||
new_fops = fops_get(c->fops);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (new_fops == NULL) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
err = 0;
|
||||
|
||||
old_fops = file->f_op;
|
||||
file->f_op = new_fops;
|
||||
if (file->f_op->open) {
|
||||
file->private_data = c;
|
||||
err = file->f_op->open(inode, file);
|
||||
if (err) {
|
||||
fops_put(file->f_op);
|
||||
file->private_data = NULL;
|
||||
file->f_op = fops_get(old_fops);
|
||||
}
|
||||
}
|
||||
|
||||
fops_put(old_fops);
|
||||
fail:
|
||||
mutex_unlock(&media_sem);
|
||||
return err;
|
||||
}
|
||||
|
||||
static struct file_operations media_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = media_open,
|
||||
};
|
||||
|
||||
/**
|
||||
* media_register - register a media device
|
||||
* @media: device structure
|
||||
*
|
||||
* Register a media device with the kernel. If the minor
|
||||
* number is set to %MEDIA_DYNAMIC_MINOR a minor number is assigned
|
||||
* and placed in the minor field of the structure. For other cases
|
||||
* the minor number requested is used.
|
||||
*
|
||||
* The structure passed is linked into the kernel and may not be
|
||||
* destroyed until it has been unregistered.
|
||||
*
|
||||
* A zero is returned on success and a negative errno code for
|
||||
* failure.
|
||||
*/
|
||||
|
||||
int media_register(struct media_device *media)
|
||||
{
|
||||
struct media_device *ptmp = NULL;
|
||||
struct media_driver *pdrv = NULL;
|
||||
|
||||
int err = 0;
|
||||
|
||||
mutex_lock(&media_sem);
|
||||
|
||||
/* check if registered */
|
||||
osal_list_for_each_entry(ptmp, &media_list, list) {
|
||||
if (ptmp->minor == media->minor) {
|
||||
mutex_unlock(&media_sem);
|
||||
return -EBUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/* check minor */
|
||||
if (media->minor == MEDIA_DYNAMIC_MINOR) {
|
||||
int i = DYNAMIC_MINORS;
|
||||
|
||||
while (--i >= 0)
|
||||
if ((media_minors[(unsigned int)i >> 3] & (1 << ((unsigned int)i & 7))) == 0) {
|
||||
break;
|
||||
}
|
||||
if (i < 0) {
|
||||
mutex_unlock(&media_sem);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
media->minor = i;
|
||||
}
|
||||
|
||||
if (media->minor < DYNAMIC_MINORS) {
|
||||
media_minors[media->minor >> 3] |= 1 << (media->minor & 7);
|
||||
}
|
||||
|
||||
/* device register */
|
||||
err = _media_device_register(media);
|
||||
if (err < 0) {
|
||||
media_minors[media->minor >> 3] &= ~(1 << (media->minor & 7));
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* driver register */
|
||||
pdrv = media_driver_register(media->devfs_name, media->owner, media->drvops);
|
||||
if (IS_ERR(pdrv)) {
|
||||
_media_device_unregister(media);
|
||||
|
||||
media_minors[media->minor >> 3] &= ~(1 << (media->minor & 7));
|
||||
|
||||
err = PTR_ERR(pdrv);
|
||||
goto out;
|
||||
}
|
||||
|
||||
media->driver = pdrv;
|
||||
|
||||
/*
|
||||
* Add it to the front, so that later devices can "override"
|
||||
* earlier defaults
|
||||
*/
|
||||
osal_list_add(&media->list, &media_list);
|
||||
|
||||
out:
|
||||
mutex_unlock(&media_sem);
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(media_register);
|
||||
|
||||
/**
|
||||
* media_unregister - unregister a media device
|
||||
* @media: device to unregister
|
||||
*
|
||||
* Unregister a media device that was previously
|
||||
* successfully registered with media_register(). Success
|
||||
* is indicated by a zero return, a negative errno code
|
||||
* indicates an error.
|
||||
*/
|
||||
|
||||
int media_unregister(struct media_device *media)
|
||||
{
|
||||
struct media_device *ptmp = NULL, *_ptmp = NULL;
|
||||
|
||||
if (osal_list_empty(&media->list)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_lock(&media_sem);
|
||||
|
||||
osal_list_for_each_entry_safe(ptmp, _ptmp, &media_list, list) {
|
||||
/* if found, unregister device & driver */
|
||||
if (ptmp->minor == media->minor) {
|
||||
osal_list_del(&media->list);
|
||||
|
||||
media_driver_unregister(media->driver);
|
||||
|
||||
media->driver = NULL;
|
||||
|
||||
_media_device_unregister(media);
|
||||
|
||||
media_minors[media->minor >> 3] &= ~(1 << (media->minor & 7));
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&media_sem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(media_unregister);
|
||||
|
||||
int media_init(void)
|
||||
{
|
||||
int ret;
|
||||
// 1
|
||||
ret = media_bus_init();
|
||||
if (ret) {
|
||||
goto err0;
|
||||
}
|
||||
|
||||
// 2
|
||||
ret = -EIO;
|
||||
|
||||
if (register_chrdev(MEDIA_DEVICE_MAJOR, "media", &media_fops)) {
|
||||
goto err1;
|
||||
}
|
||||
|
||||
printk("Module media: init ok\n");
|
||||
|
||||
return 0;
|
||||
|
||||
// 3
|
||||
err1:
|
||||
media_bus_exit();
|
||||
err0:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void media_exit(void)
|
||||
{
|
||||
// 0
|
||||
if (!osal_list_empty(&media_list)) {
|
||||
printk("!!! Module media: sub module in list\n");
|
||||
return;
|
||||
}
|
||||
|
||||
unregister_chrdev(MEDIA_DEVICE_MAJOR, "media");
|
||||
|
||||
media_bus_exit();
|
||||
|
||||
printk("!!! Module media: exit ok\n");
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright (c) XMEDIA. All rights reserved.
|
||||
*/
|
||||
#ifndef _LINUX_MEDIA_DEVICE_H_
|
||||
#define _LINUX_MEDIA_DEVICE_H_
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/major.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/devfreq.h>
|
||||
#include "osal_list.h"
|
||||
#include "osal_devfreq.h"
|
||||
|
||||
#define MEDIA_DEVICE_MAJOR 218
|
||||
#define MEDIA_DYNAMIC_MINOR 255
|
||||
|
||||
struct media_device;
|
||||
|
||||
struct media_ops {
|
||||
// pm methos
|
||||
int (*pm_prepare)(struct media_device *);
|
||||
void (*pm_complete)(struct media_device *);
|
||||
|
||||
int (*pm_suspend)(struct media_device *);
|
||||
int (*pm_resume)(struct media_device *);
|
||||
|
||||
int (*pm_freeze)(struct media_device *);
|
||||
int (*pm_thaw)(struct media_device *);
|
||||
int (*pm_poweroff)(struct media_device *);
|
||||
int (*pm_restore)(struct media_device *);
|
||||
|
||||
int (*pm_suspend_late)(struct media_device *);
|
||||
int (*pm_resume_early)(struct media_device *);
|
||||
int (*pm_freeze_late)(struct media_device *);
|
||||
int (*pm_thaw_early)(struct media_device *);
|
||||
int (*pm_poweroff_late)(struct media_device *);
|
||||
int (*pm_restore_early)(struct media_device *);
|
||||
|
||||
int (*pm_suspend_noirq)(struct media_device *);
|
||||
int (*pm_resume_noirq)(struct media_device *);
|
||||
|
||||
int (*pm_freeze_noirq)(struct media_device *);
|
||||
int (*pm_thaw_noirq)(struct media_device *);
|
||||
int (*pm_poweroff_noirq)(struct media_device *);
|
||||
int (*pm_restore_noirq)(struct media_device *);
|
||||
|
||||
/* devfreq */
|
||||
int (*devfreq_target)(struct media_device *, unsigned long *, unsigned int);
|
||||
int (*devfreq_get_dev_status)(struct media_device *, struct osal_devfreq_dev_status *);
|
||||
int (*devfreq_get_cur_freq)(struct media_device *, unsigned long *);
|
||||
void (*devfreq_exit)(struct media_device *);
|
||||
};
|
||||
|
||||
#define MEDIA_MAX_DEV_NAME_LEN 32
|
||||
|
||||
struct media_driver {
|
||||
struct device_driver driver;
|
||||
struct media_ops *ops;
|
||||
char name[1];
|
||||
};
|
||||
|
||||
#define to_media_driver(drv) \
|
||||
container_of((drv), struct media_driver, driver)
|
||||
|
||||
struct media_device {
|
||||
struct osal_list_head list;
|
||||
|
||||
char devfs_name[MEDIA_MAX_DEV_NAME_LEN];
|
||||
|
||||
unsigned int minor;
|
||||
|
||||
struct device device;
|
||||
|
||||
struct module *owner;
|
||||
|
||||
const struct file_operations *fops;
|
||||
|
||||
struct media_ops *drvops;
|
||||
|
||||
/* for internal use */
|
||||
struct media_driver *driver;
|
||||
|
||||
struct devfreq *devfreq;
|
||||
struct devfreq_dev_profile profile;
|
||||
};
|
||||
|
||||
#define to_media_device(dev) \
|
||||
container_of((dev), struct media_device, device)
|
||||
|
||||
int media_devfreq_register(struct media_device *media, osal_devfreq_para_t *devfreq_para);
|
||||
void media_devfreq_unregister(struct media_device *media);
|
||||
|
||||
int media_register(struct media_device *pdev);
|
||||
|
||||
int media_unregister(struct media_device *pdev);
|
||||
|
||||
#define MODULE_ALIAS_MEDIA(minor) \
|
||||
MODULE_ALIAS("media-char-major-" __stringify(MEDIA_DEVICE_MAJOR) "-" __stringify(minor))
|
||||
|
||||
#endif /* _LINUX_MEDIA_DEVICE_H_ */
|
||||
@@ -0,0 +1,419 @@
|
||||
/*
|
||||
* Copyright (c) XMEDIA. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/fs.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/delay.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/list.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <linux/version.h>
|
||||
#include "allocator.h"
|
||||
|
||||
#ifndef fallthrough
|
||||
#define fallthrough
|
||||
#endif
|
||||
|
||||
extern struct osal_list_head mmz_list;
|
||||
|
||||
long long max_malloc_size = 0x40000000UL;
|
||||
|
||||
static unsigned long _strtoul_ex(const char *s, char **ep, unsigned int base)
|
||||
{
|
||||
char *__end_p = NULL;
|
||||
unsigned long __value;
|
||||
|
||||
__value = simple_strtoul(s, &__end_p, base);
|
||||
|
||||
switch (*__end_p) {
|
||||
case 'm':
|
||||
fallthrough;
|
||||
case 'M':
|
||||
__value <<= 10;
|
||||
fallthrough;
|
||||
case 'k':
|
||||
fallthrough;
|
||||
case 'K':
|
||||
__value <<= 10;
|
||||
if (ep != NULL) {
|
||||
(*ep) = __end_p + 1;
|
||||
}
|
||||
fallthrough;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return __value;
|
||||
}
|
||||
|
||||
static unsigned long find_fixed_region(unsigned long *region_len,
|
||||
mmz_mmz_t *mmz,
|
||||
unsigned long size,
|
||||
unsigned long align)
|
||||
{
|
||||
unsigned long start;
|
||||
unsigned long fixed_start = 0;
|
||||
unsigned long fixed_len = -1;
|
||||
unsigned long len = 0;
|
||||
unsigned long blank_len = 0;
|
||||
mmz_mmb_t *p = NULL;
|
||||
|
||||
mmz_trace_func();
|
||||
align = mmz_grain_align(align);
|
||||
if (align == 0) {
|
||||
align = MMZ_GRAIN;
|
||||
}
|
||||
start = mmz_align2(mmz->phys_start, align);
|
||||
len = mmz_grain_align(size);
|
||||
|
||||
list_for_each_entry(p, &mmz->mmb_list, list) {
|
||||
mmz_mmb_t *next = NULL;
|
||||
mmz_trace(4, "p->phys_addr=0x%08lX p->length = %luKB \t",
|
||||
p->phys_addr, p->length / SZ_1K);
|
||||
next = list_entry(p->list.next, typeof(*p), list);
|
||||
mmz_trace(4, ",next = 0x%08lX\n\n", next->phys_addr);
|
||||
/*
|
||||
* if p is the first entry or not.
|
||||
*/
|
||||
if (list_first_entry(&mmz->mmb_list, typeof(*p), list) == p) {
|
||||
blank_len = p->phys_addr - start;
|
||||
if ((blank_len < fixed_len) && (blank_len >= len)) {
|
||||
fixed_len = blank_len;
|
||||
fixed_start = start;
|
||||
mmz_trace(4, "%d: fixed_region: start=0x%08lX, len=%luKB\n",
|
||||
__LINE__, fixed_start, fixed_len / SZ_1K);
|
||||
}
|
||||
}
|
||||
start = mmz_align2((p->phys_addr + p->length), align);
|
||||
/*
|
||||
* if aglin is larger than mmz->nbytes, it would trigger the BUG_ON
|
||||
*/
|
||||
// BUG_ON((start < mmz->phys_start) || (start > (mmz->phys_start + mmz->nbytes)));
|
||||
/*
|
||||
* if we have to alloc after the last node.
|
||||
*/
|
||||
if (osal_list_is_last(&p->list, &mmz->mmb_list)) {
|
||||
blank_len = mmz->phys_start + mmz->nbytes - start;
|
||||
if ((blank_len < fixed_len) && (blank_len >= len)) {
|
||||
fixed_len = blank_len;
|
||||
fixed_start = start;
|
||||
mmz_trace(4, "fixed_region: start=0x%08lX, len=%luKB\n",
|
||||
fixed_start, fixed_len / SZ_1K);
|
||||
break;
|
||||
} else {
|
||||
if (fixed_len != -1) {
|
||||
goto out;
|
||||
}
|
||||
fixed_start = 0;
|
||||
mmz_trace(4, "fixed_region: start=0x%08lX, len=%luKB\n",
|
||||
fixed_start, fixed_len / SZ_1K);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
/* blank is too small */
|
||||
if ((start + len) > next->phys_addr) {
|
||||
mmz_trace(4, "start=0x%08lX ,len=%lu,next=0x%08lX\n",
|
||||
start, len, next->phys_addr);
|
||||
continue;
|
||||
}
|
||||
blank_len = next->phys_addr - start;
|
||||
if ((blank_len < fixed_len) && (blank_len >= len)) {
|
||||
fixed_len = blank_len;
|
||||
fixed_start = start;
|
||||
mmz_trace(4, "fixed_region: start=0x%08lX, len=%luKB\n",
|
||||
fixed_start, fixed_len / SZ_1K);
|
||||
}
|
||||
}
|
||||
|
||||
if ((mmz_grain_align(start + len) <= (mmz->phys_start + mmz->nbytes)) &&
|
||||
(start >= mmz->phys_start) &&
|
||||
(start < (mmz->phys_start + mmz->nbytes))) {
|
||||
fixed_len = len;
|
||||
fixed_start = start;
|
||||
mmz_trace(4, "fixed_region: start=0x%08lX, len=%luKB\n",
|
||||
fixed_start, fixed_len / SZ_1K);
|
||||
} else {
|
||||
fixed_start = 0;
|
||||
mmz_trace(4, "fixed_region: start=0x%08lX, len=%luKB\n",
|
||||
fixed_start, len / SZ_1K);
|
||||
}
|
||||
out:
|
||||
*region_len = len;
|
||||
return fixed_start;
|
||||
}
|
||||
|
||||
static int do_mmb_alloc(mmz_mmb_t *mmb)
|
||||
{
|
||||
mmz_mmb_t *p = NULL;
|
||||
mmz_trace_func();
|
||||
|
||||
/* add mmb sorted */
|
||||
osal_list_for_each_entry(p, &mmb->zone->mmb_list, list) {
|
||||
if (mmb->phys_addr < p->phys_addr) {
|
||||
break;
|
||||
}
|
||||
if (mmb->phys_addr == p->phys_addr) {
|
||||
printk(KERN_ERR "ERROR: media-mem allocator bad in %s! (%s, %d)",
|
||||
mmb->zone->name, __FUNCTION__, __LINE__);
|
||||
}
|
||||
}
|
||||
osal_list_add(&mmb->list, p->list.prev);
|
||||
|
||||
mmz_trace(1, MMZ_MMB_FMT_S, mmz_mmb_fmt_arg(mmb));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static mmz_mmb_t *__mmb_alloc(const char *name,
|
||||
unsigned long size,
|
||||
unsigned long align,
|
||||
unsigned long gfp,
|
||||
const char *mmz_name,
|
||||
mmz_mmz_t *_user_mmz)
|
||||
{
|
||||
mmz_mmz_t *mmz = NULL;
|
||||
mmz_mmb_t *mmb = NULL;
|
||||
|
||||
unsigned long start;
|
||||
unsigned long region_len;
|
||||
|
||||
unsigned long fixed_start = 0;
|
||||
unsigned long fixed_len = ~1;
|
||||
mmz_mmz_t *fixed_mmz = NULL;
|
||||
|
||||
mmz_trace_func();
|
||||
|
||||
if ((size == 0) || (size > max_malloc_size)) {
|
||||
return NULL;
|
||||
}
|
||||
if (align == 0) {
|
||||
align = MMZ_GRAIN;
|
||||
}
|
||||
|
||||
size = mmz_grain_align(size);
|
||||
|
||||
mmz_trace(1, "size=%luKB, align=%lu", size / SZ_1K, align);
|
||||
|
||||
begin_list_for_each_mmz(mmz, gfp, mmz_name)
|
||||
|
||||
if ((_user_mmz != NULL) && (_user_mmz != mmz)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
start = find_fixed_region(®ion_len, mmz, size, align);
|
||||
if ((fixed_len > region_len) && (start != 0)) {
|
||||
fixed_len = region_len;
|
||||
fixed_start = start;
|
||||
fixed_mmz = mmz;
|
||||
}
|
||||
end_list_for_each_mmz()
|
||||
|
||||
if (fixed_mmz == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mmb = kmalloc(sizeof(mmz_mmb_t), GFP_KERNEL);
|
||||
if (mmb == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(mmb, 0, sizeof(mmz_mmb_t));
|
||||
mmb->zone = fixed_mmz;
|
||||
mmb->phys_addr = fixed_start;
|
||||
mmb->length = size;
|
||||
if (name != NULL) {
|
||||
strlcpy(mmb->name, name, MMZ_MMB_NAME_LEN);
|
||||
} else {
|
||||
strncpy(mmb->name, "<null>", MMZ_MMB_NAME_LEN);
|
||||
}
|
||||
|
||||
if (do_mmb_alloc(mmb)) {
|
||||
kfree(mmb);
|
||||
mmb = NULL;
|
||||
}
|
||||
|
||||
return mmb;
|
||||
}
|
||||
|
||||
static void *__mmb_map2kern(mmz_mmb_t *mmb, int cached)
|
||||
{
|
||||
/*
|
||||
* already mapped? no need to remap again,
|
||||
* just return mmb's kernel virtual address.
|
||||
*/
|
||||
if (mmb->flags & MMZ_MMB_MAP2KERN) {
|
||||
if ((!!cached * MMZ_MMB_MAP2KERN_CACHED) != (mmb->flags & MMZ_MMB_MAP2KERN_CACHED)) {
|
||||
printk(KERN_ERR "mmb<%s> has been kernel-mapped as %s, \
|
||||
can not be re-mapped as %s.",
|
||||
mmb->name,
|
||||
(mmb->flags & MMZ_MMB_MAP2KERN_CACHED) ? "cached" : "non-cached",
|
||||
(cached) ? "cached" : "non-cached");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mmb->map_ref++;
|
||||
|
||||
return mmb->kvirt;
|
||||
}
|
||||
|
||||
if (cached) {
|
||||
mmb->flags |= MMZ_MMB_MAP2KERN_CACHED;
|
||||
mmb->kvirt = ioremap_cache(mmb->phys_addr, mmb->length);
|
||||
} else {
|
||||
mmb->flags &= ~MMZ_MMB_MAP2KERN_CACHED;
|
||||
/* ioremap_wc has better performance */
|
||||
mmb->kvirt = ioremap_wc(mmb->phys_addr, mmb->length);
|
||||
}
|
||||
|
||||
if (mmb->kvirt) {
|
||||
mmb->flags |= MMZ_MMB_MAP2KERN;
|
||||
mmb->map_ref++;
|
||||
} else {
|
||||
mmb->flags &= ~MMZ_MMB_MAP2KERN_CACHED;
|
||||
}
|
||||
|
||||
return mmb->kvirt;
|
||||
}
|
||||
|
||||
static void __mmb_free(mmz_mmb_t *mmb)
|
||||
{
|
||||
if (mmb->flags & MMZ_MMB_MAP2KERN_CACHED) {
|
||||
#ifdef CONFIG_64BIT
|
||||
__flush_dcache_area((void *)mmb->kvirt, (size_t)mmb->length);
|
||||
#else
|
||||
__cpuc_flush_dcache_area((void *)mmb->kvirt, (size_t)mmb->length);
|
||||
outer_flush_range(mmb->phys_addr, mmb->phys_addr + mmb->length);
|
||||
#endif
|
||||
}
|
||||
|
||||
osal_list_del(&mmb->list);
|
||||
kfree(mmb);
|
||||
}
|
||||
|
||||
static int __mmb_unmap(mmz_mmb_t *mmb)
|
||||
{
|
||||
int ref;
|
||||
|
||||
if (mmb->flags & MMZ_MMB_MAP2KERN_CACHED) {
|
||||
#ifdef CONFIG_64BIT
|
||||
__flush_dcache_area((void *)mmb->kvirt, (size_t)mmb->length);
|
||||
#else
|
||||
__cpuc_flush_dcache_area((void *)mmb->kvirt, (size_t)mmb->length);
|
||||
outer_flush_range(mmb->phys_addr, mmb->phys_addr + mmb->length);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (mmb->flags & MMZ_MMB_MAP2KERN) {
|
||||
ref = --mmb->map_ref;
|
||||
if (mmb->map_ref != 0) {
|
||||
return ref;
|
||||
}
|
||||
iounmap(mmb->kvirt);
|
||||
}
|
||||
|
||||
mmb->kvirt = NULL;
|
||||
mmb->flags &= ~MMZ_MMB_MAP2KERN;
|
||||
mmb->flags &= ~MMZ_MMB_MAP2KERN_CACHED;
|
||||
|
||||
if ((mmb->flags & MMZ_MMB_RELEASED) && (mmb->phy_ref == 0)) {
|
||||
__mmb_free(mmb);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void *__mmf_map(phys_addr_t phys, int len, int cache)
|
||||
{
|
||||
void *virt = NULL;
|
||||
if (cache) {
|
||||
virt = ioremap_cache(phys, len);
|
||||
} else {
|
||||
virt = ioremap_wc(phys, len);
|
||||
}
|
||||
|
||||
return virt;
|
||||
}
|
||||
|
||||
static void __mmf_unmap(void *virt)
|
||||
{
|
||||
if (virt != NULL) {
|
||||
iounmap(virt);
|
||||
}
|
||||
}
|
||||
|
||||
static int __allocator_init(char *s)
|
||||
{
|
||||
mmz_mmz_t *zone = NULL;
|
||||
char *line = NULL;
|
||||
unsigned long phys_end = 0;
|
||||
|
||||
while ((line = strsep(&s, ":")) != NULL) {
|
||||
int i;
|
||||
char *argv[6];
|
||||
|
||||
for (i = 0; (argv[i] = strsep(&line, ",")) != NULL;)
|
||||
if (++i == ARRAY_SIZE(argv)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == 4) {
|
||||
zone = mmz_mmz_create("null", 0, 0, 0);
|
||||
if (zone == NULL) {
|
||||
continue;
|
||||
}
|
||||
strlcpy(zone->name, argv[0], MMZ_MMZ_NAME_LEN);
|
||||
zone->gfp = _strtoul_ex(argv[1], NULL, 0);
|
||||
zone->phys_start = _strtoul_ex(argv[2], NULL, 0);
|
||||
zone->nbytes = _strtoul_ex(argv[3], NULL, 0);
|
||||
if (zone->nbytes > max_malloc_size) {
|
||||
max_malloc_size = zone->nbytes;
|
||||
}
|
||||
} else {
|
||||
printk(KERN_ERR "error parameters\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
// mmz_info_phys_start = zone->phys_start + zone->nbytes - 0x2000;
|
||||
|
||||
if (mmz_mmz_register(zone)) {
|
||||
printk(KERN_WARNING "Add MMZ failed: " MMZ_MMZ_FMT_S "\n", mmz_mmz_fmt_arg(zone));
|
||||
mmz_mmz_destroy(zone);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// if phys_end is 0xFFFFFFFF (32bit)
|
||||
phys_end = (zone->phys_start + zone->nbytes);
|
||||
|
||||
if ((phys_end == 0) && (zone->nbytes >= PAGE_SIZE)) {
|
||||
// reserve last PAGE_SIZE memory
|
||||
zone->nbytes = zone->nbytes - PAGE_SIZE;
|
||||
}
|
||||
|
||||
// if phys_end exceed 0xFFFFFFFF (32bit), wraping error
|
||||
if ((zone->phys_start > phys_end) && (phys_end != 0)) {
|
||||
printk(KERN_ERR "MMZ: parameter is not correct! Address exceeds 0xFFFFFFFF\n");
|
||||
mmz_mmz_unregister(zone);
|
||||
mmz_mmz_destroy(zone);
|
||||
return -1;
|
||||
}
|
||||
zone = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int allocator_setopt(struct mmz_allocator *allocator)
|
||||
{
|
||||
allocator->init = __allocator_init;
|
||||
allocator->mmb_alloc = __mmb_alloc;
|
||||
allocator->mmb_map2kern = __mmb_map2kern;
|
||||
allocator->mmb_unmap = __mmb_unmap;
|
||||
allocator->mmb_free = __mmb_free;
|
||||
allocator->mmf_map = __mmf_map;
|
||||
allocator->mmf_unmap = __mmf_unmap;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) XMEDIA. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __ALLOCATOR_H__
|
||||
#define __ALLOCATOR_H__
|
||||
|
||||
#include <linux/device.h>
|
||||
#include "osal_mmz.h"
|
||||
|
||||
#define NAME_LEN_MAX 64
|
||||
|
||||
struct mmz_allocator {
|
||||
int (*init)(char *args);
|
||||
mmz_mmb_t *(*mmb_alloc)(const char *name,
|
||||
unsigned long size,
|
||||
unsigned long align,
|
||||
unsigned long gfp,
|
||||
const char *mmz_name,
|
||||
mmz_mmz_t *_user_mmz);
|
||||
void *(*mmb_map2kern)(mmz_mmb_t *mmb, int cached);
|
||||
int (*mmb_unmap)(mmz_mmb_t *mmb);
|
||||
void (*mmb_free)(mmz_mmb_t *mmb);
|
||||
void *(*mmf_map)(phys_addr_t phys, int len, int cache);
|
||||
void (*mmf_unmap)(void *virt);
|
||||
};
|
||||
|
||||
int cma_allocator_setopt(struct mmz_allocator *allocator);
|
||||
int allocator_setopt(struct mmz_allocator *allocator);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,459 @@
|
||||
/*
|
||||
* Copyright (c) XMEDIA. All rights reserved.
|
||||
*/
|
||||
#include <linux/fs.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/delay.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/list.h>
|
||||
#include <asm/cacheflush.h>
|
||||
|
||||
#include <asm/memory.h>
|
||||
#include <linux/dma-contiguous.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <asm/memory.h>
|
||||
#include <asm/tlbflush.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <linux/vmalloc.h>
|
||||
|
||||
#include "allocator.h"
|
||||
#include "mmz_arm.h"
|
||||
|
||||
#define __use_vmalloc_space 1
|
||||
|
||||
struct cma_zone {
|
||||
struct device pdev;
|
||||
char name[NAME_LEN_MAX];
|
||||
unsigned long gfp;
|
||||
unsigned long phys_start;
|
||||
unsigned long nbytes;
|
||||
unsigned int alloc_type;
|
||||
unsigned long block_align;
|
||||
};
|
||||
|
||||
extern struct osal_list_head mmz_list;
|
||||
|
||||
long long max_malloc_size = 0x40000000UL;
|
||||
|
||||
static int do_mmb_alloc(mmz_mmb_t *mmb)
|
||||
{
|
||||
mmz_mmb_t *p = NULL;
|
||||
mmz_trace_func();
|
||||
|
||||
/* add mmb into zone, sorted */
|
||||
osal_list_for_each_entry(p, &mmb->zone->mmb_list, list) {
|
||||
if (mmb->phys_addr < p->phys_addr) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (mmb->phys_addr == p->phys_addr) {
|
||||
pr_err("ERROR:cma allocator bad in %s(%s, %d)",
|
||||
mmb->zone->name, __func__, __LINE__);
|
||||
return -EFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
osal_list_add(&mmb->list, p->list.prev);
|
||||
mmz_trace(1, MMZ_MMB_FMT_S, mmz_mmb_fmt_arg(mmb));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static mmz_mmb_t *__mmb_alloc(const char *name,
|
||||
unsigned long size,
|
||||
unsigned long align,
|
||||
unsigned long gfp,
|
||||
const char *mmz_name,
|
||||
mmz_mmz_t *_user_mmz)
|
||||
{
|
||||
mmz_mmz_t *mmz = NULL;
|
||||
mmz_mmb_t *mmb = NULL;
|
||||
unsigned long order = get_order(size);
|
||||
size_t count = size >> PAGE_SHIFT;
|
||||
struct page *page = NULL;
|
||||
|
||||
mmz_trace_func();
|
||||
|
||||
/*
|
||||
* No zero length memory request, no supper
|
||||
* large memory (4GB and above) request.
|
||||
*/
|
||||
if ((size == 0) || (size > max_malloc_size)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (align == 0) {
|
||||
align = MMZ_GRAIN;
|
||||
}
|
||||
|
||||
size = mmz_grain_align(size);
|
||||
order = get_order(size);
|
||||
count = size >> PAGE_SHIFT;
|
||||
|
||||
mmz_trace(1, "anonymous=%s,size=%luKB,align=%lu", mmz_name, size / SZ_1K, align);
|
||||
|
||||
begin_list_for_each_mmz(mmz, gfp, mmz_name)
|
||||
|
||||
if ((_user_mmz != NULL) && (_user_mmz != mmz)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
page = dma_alloc_from_contiguous(mmz->cma_dev, count, order);
|
||||
if (page == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Get it */
|
||||
break;
|
||||
end_list_for_each_mmz()
|
||||
|
||||
if (page == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* clear the allocated buffer, if needed! */
|
||||
dma_buffer_clear(page, size);
|
||||
|
||||
mmb = kmalloc(sizeof(mmz_mmb_t), GFP_KERNEL);
|
||||
if (mmb == NULL) {
|
||||
pr_err("<%s,%d> mmb struct alloc failed\n", __func__, __LINE__);
|
||||
goto cma_free;
|
||||
}
|
||||
|
||||
memset(mmb, 0, sizeof(mmz_mmb_t));
|
||||
mmb->zone = mmz;
|
||||
mmb->phys_addr = page_to_phys(page);
|
||||
mmb->length = size;
|
||||
|
||||
if (name != NULL) {
|
||||
strlcpy(mmb->name, name, MMZ_MMB_NAME_LEN);
|
||||
} else {
|
||||
strncpy(mmb->name, "<null>", MMZ_MMB_NAME_LEN - 1);
|
||||
}
|
||||
|
||||
if (do_mmb_alloc(mmb)) {
|
||||
goto mmb_free;
|
||||
}
|
||||
|
||||
return mmb;
|
||||
|
||||
mmb_free:
|
||||
kfree(mmb);
|
||||
cma_free:
|
||||
dma_release_from_contiguous(mmz->cma_dev, page, count);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void __mmb_free(mmz_mmb_t *mmb)
|
||||
{
|
||||
size_t count = mmb->length >> PAGE_SHIFT;
|
||||
struct page *page = phys_to_page(mmb->phys_addr);
|
||||
|
||||
mmz_mmz_t *mmz = mmb->zone;
|
||||
|
||||
if (mmb->flags & MMZ_MMB_MAP2KERN_CACHED) {
|
||||
mmb_dcache_flush(mmb);
|
||||
}
|
||||
|
||||
dma_release_from_contiguous(mmz->cma_dev, page, count);
|
||||
|
||||
osal_list_del(&mmb->list);
|
||||
kfree(mmb);
|
||||
}
|
||||
|
||||
static void *__mmb_map2kern(mmz_mmb_t *mmb, int cached)
|
||||
{
|
||||
pgprot_t prot;
|
||||
struct page *page = phys_to_page(mmb->phys_addr);
|
||||
|
||||
mmz_trace(1, "mmb[phys_addr=%lx,kvirt=%pK,length=%lx]",
|
||||
mmb->phys_addr, mmb->kvirt, mmb->length);
|
||||
|
||||
if (mmb->flags & MMZ_MMB_MAP2KERN) {
|
||||
if ((!!cached * MMZ_MMB_MAP2KERN_CACHED) != (mmb->flags & MMZ_MMB_MAP2KERN_CACHED)) {
|
||||
pr_err("mmb<%s> has been kernel-mapped %s, \
|
||||
can not be re-mapped as %s.",
|
||||
mmb->name,
|
||||
(mmb->flags & MMZ_MMB_MAP2KERN_CACHED) ? "cached" : "non-cached",
|
||||
(cached) ? "cached" : "non-cached");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mmz_trace(1, "map[%lx --> %pK]", mmb->phys_addr, mmb->kvirt);
|
||||
|
||||
mmb->map_ref++;
|
||||
return mmb->kvirt;
|
||||
}
|
||||
|
||||
prot = arch_kern_pgprot(cached);
|
||||
|
||||
#if __use_vmalloc_space
|
||||
/*
|
||||
* Map into vmalloc space
|
||||
*/
|
||||
{
|
||||
int i;
|
||||
struct page **pages = NULL;
|
||||
unsigned int pagesnr = mmb->length / PAGE_SIZE;
|
||||
struct page *tmp = page;
|
||||
int array_size = sizeof(struct page *) * pagesnr;
|
||||
|
||||
/*
|
||||
* Noted: mmb->length would be very large in some cases(for example:
|
||||
* more than one Giga Bytes). and array_size would be very large as
|
||||
* well. So, don't use kmalloc here.
|
||||
*/
|
||||
pages = vmalloc(array_size);
|
||||
if (pages == NULL) {
|
||||
pr_err("ptr array(0x%x) vmalloc failed.\n", array_size);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < pagesnr; i++) {
|
||||
*(pages + i) = tmp;
|
||||
tmp++;
|
||||
}
|
||||
|
||||
mmb->kvirt = vmap(pages, pagesnr, VM_MAP, prot);
|
||||
vfree(pages);
|
||||
}
|
||||
#else
|
||||
/*
|
||||
* Map into linear space
|
||||
*/
|
||||
{
|
||||
dma_pages_remap(page, mmb->length, prot);
|
||||
mmb->kvirt = __va(mmb->phys_addr);
|
||||
}
|
||||
#endif
|
||||
if (mmb->kvirt == NULL) {
|
||||
/*
|
||||
* you should never get here.
|
||||
*/
|
||||
printk(KERN_ERR "mmb[0x%lx, 0x%lx] map to kernel failed\n",
|
||||
mmb->phys_addr, mmb->length);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (cached) {
|
||||
mmb->flags |= MMZ_MMB_MAP2KERN_CACHED;
|
||||
} else {
|
||||
mmb->flags &= ~MMZ_MMB_MAP2KERN_CACHED;
|
||||
}
|
||||
mmb->flags |= MMZ_MMB_MAP2KERN;
|
||||
mmb->map_ref++;
|
||||
|
||||
mmz_trace(1, "map[%lx --> %pK]", mmb->phys_addr, mmb->kvirt);
|
||||
|
||||
return mmb->kvirt;
|
||||
}
|
||||
|
||||
static int __mmb_unmap(mmz_mmb_t *mmb)
|
||||
{
|
||||
int ref;
|
||||
|
||||
mmz_trace(1, "mmb[phys_addr=%lx,kvirt=%pK,length=%lx]",
|
||||
mmb->phys_addr, mmb->kvirt, mmb->length);
|
||||
|
||||
if (mmb->flags & MMZ_MMB_MAP2KERN_CACHED) {
|
||||
mmb_dcache_flush(mmb);
|
||||
}
|
||||
|
||||
if (mmb->flags & MMZ_MMB_MAP2KERN) {
|
||||
ref = --mmb->map_ref;
|
||||
if (mmb->map_ref != 0) {
|
||||
return ref;
|
||||
}
|
||||
}
|
||||
|
||||
#if __use_vmalloc_space
|
||||
/*
|
||||
* unmap from vmalloc space.
|
||||
*/
|
||||
{
|
||||
vunmap(mmb->kvirt);
|
||||
}
|
||||
#endif
|
||||
mmb->kvirt = NULL;
|
||||
mmb->flags &= ~MMZ_MMB_MAP2KERN;
|
||||
mmb->flags &= ~MMZ_MMB_MAP2KERN_CACHED;
|
||||
|
||||
if ((mmb->flags & MMZ_MMB_RELEASED) && (mmb->phy_ref == 0)) {
|
||||
__mmb_free(mmb);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Map any valid phys address passed by users, to virtual address.
|
||||
* The input phys may not be 4Kbytes aligned.
|
||||
* FIXME
|
||||
*/
|
||||
static void *__mmf_map(phys_addr_t phys, int len, int cache)
|
||||
{
|
||||
struct page **pages = NULL;
|
||||
unsigned int pagesnr = len / PAGE_SIZE;
|
||||
int i;
|
||||
void *virt = NULL;
|
||||
pgprot_t prot;
|
||||
struct page *page = phys_to_page(phys);
|
||||
struct page *tmp = page;
|
||||
int array_size;
|
||||
|
||||
mmz_trace(1, "phys=%lx, len=0x%x, cache=%d", (unsigned long)phys, len, cache);
|
||||
|
||||
/*
|
||||
* if the given phys is not page aligned, we need to
|
||||
* map one more page for the leftover.
|
||||
*/
|
||||
if (((phys & 0xfff) + len) > PAGE_SIZE) {
|
||||
pagesnr += 1;
|
||||
}
|
||||
|
||||
array_size = sizeof(struct page *) * pagesnr;
|
||||
|
||||
prot = arch_kern_pgprot(cache);
|
||||
|
||||
#if __use_vmalloc_space
|
||||
/*
|
||||
* Map into vmalloc space.
|
||||
*/
|
||||
{
|
||||
/*
|
||||
* Noted: length of region may be very large in some cases(for example:
|
||||
* more than one Giga Bytes). and array_size would be very large as
|
||||
* well. So, don't use kmalloc here.
|
||||
*/
|
||||
pages = vmalloc(array_size);
|
||||
if (pages == NULL) {
|
||||
printk(KERN_ERR "ptr vmalloc %d failed.\n", array_size);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < pagesnr; i++) {
|
||||
*(pages + i) = tmp;
|
||||
tmp++;
|
||||
}
|
||||
|
||||
virt = vmap(pages, pagesnr, VM_MAP, prot);
|
||||
vfree(pages);
|
||||
|
||||
if (virt == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
virt += (phys & 0xfff);
|
||||
}
|
||||
#else
|
||||
/*
|
||||
* Map into linear space
|
||||
*/
|
||||
{
|
||||
dma_pages_remap(page, len, prot);
|
||||
virt = __va(phys);
|
||||
}
|
||||
#endif
|
||||
|
||||
mmz_trace(1, "map[%lx --> %pK]", (unsigned long)phys, virt);
|
||||
|
||||
return virt;
|
||||
}
|
||||
|
||||
static void __mmf_unmap(void *virt)
|
||||
{
|
||||
unsigned long vaddr = (unsigned long)(uintptr_t)virt;
|
||||
|
||||
mmz_trace(1, "virt=%pK", virt);
|
||||
|
||||
/*
|
||||
* virtual address to be vunmaped should be page aligned
|
||||
*/
|
||||
vaddr &= 0xfffff000;
|
||||
|
||||
if ((vaddr >= VMALLOC_START) && (vaddr < VMALLOC_END)) {
|
||||
vunmap ((void *)(uintptr_t)vaddr);
|
||||
}
|
||||
}
|
||||
|
||||
static int __allocator_init(char *s)
|
||||
{
|
||||
#ifdef CONFIG_CMA
|
||||
mmz_mmz_t *zone = NULL;
|
||||
char *line = NULL;
|
||||
struct cma_zone *cma_zone = NULL;
|
||||
|
||||
while ((line = strsep(&s, ":")) != NULL) {
|
||||
int i;
|
||||
char *argv[6];
|
||||
extern struct cma_zone *get_cma_zone(const char *name);
|
||||
/*
|
||||
* FIXME: We got 4 args in "line", formated as
|
||||
* "argv[0],argv[1],argv[2],argv[3],argv[4]".
|
||||
* eg: "<mmz_name>,<gfp>,<phys_start>,<size>,<alloc_type>"
|
||||
* For more convenient, "hard code" are used such as "arg[0]", i.e.
|
||||
*/
|
||||
for (i = 0; (argv[i] = strsep(&line, ",")) != NULL;)
|
||||
if (++i == ARRAY_SIZE(argv)) {
|
||||
break;
|
||||
}
|
||||
|
||||
cma_zone = get_cma_zone(argv[0]);
|
||||
if (cma_zone == NULL) {
|
||||
printk(KERN_ERR "can't get cma zone info:%s\n", argv[0]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (i == 4) {
|
||||
zone = mmz_mmz_create("null", 0, 0, 0);
|
||||
if (zone == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
strlcpy(zone->name, argv[0], MMZ_MMZ_NAME_LEN);
|
||||
|
||||
printk("cmz zone gfp 0x%lx, phys 0x%lx, nbytes 0x%lx\n",
|
||||
cma_zone->gfp,
|
||||
cma_zone->phys_start,
|
||||
cma_zone->nbytes);
|
||||
zone->gfp = cma_zone->gfp;
|
||||
zone->phys_start = cma_zone->phys_start;
|
||||
zone->nbytes = cma_zone->nbytes;
|
||||
zone->cma_dev = &cma_zone->pdev;
|
||||
|
||||
if (zone->nbytes > max_malloc_size) {
|
||||
max_malloc_size = zone->nbytes;
|
||||
}
|
||||
} else {
|
||||
printk(KERN_ERR "Input parameter num incorrect!\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mmz_mmz_register(zone)) {
|
||||
printk(KERN_WARNING "Add MMZ failed: " MMZ_MMZ_FMT_S "\n",
|
||||
mmz_mmz_fmt_arg(zone));
|
||||
mmz_mmz_destroy(zone);
|
||||
}
|
||||
|
||||
zone = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cma_allocator_setopt(struct mmz_allocator *allocator)
|
||||
{
|
||||
allocator->init = __allocator_init;
|
||||
allocator->mmb_alloc = __mmb_alloc;
|
||||
allocator->mmb_map2kern = __mmb_map2kern;
|
||||
allocator->mmb_unmap = __mmb_unmap;
|
||||
allocator->mmb_free = __mmb_free;
|
||||
allocator->mmf_map = __mmf_map;
|
||||
allocator->mmf_unmap = __mmf_unmap;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright (c) XMEDIA. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/printk.h>
|
||||
#include <linux/semaphore.h>
|
||||
#include <linux/slab.h>
|
||||
#include "osal.h"
|
||||
#include "osal_mmz.h"
|
||||
#define MMZ_NAME "anonymous"
|
||||
|
||||
unsigned long long mmz_alloc(const char *mmz_name, const char *buf_name, unsigned long size)
|
||||
{
|
||||
mmz_mmb_t *pmmb = NULL;
|
||||
|
||||
pmmb = mmz_mmb_alloc(buf_name, size, 0, 0, mmz_name);
|
||||
if (pmmb == NULL) {
|
||||
osal_printk("Mmz malloc failed!\n");
|
||||
return 0UL;
|
||||
}
|
||||
|
||||
return mmz_mmb_phys(pmmb);
|
||||
}
|
||||
EXPORT_SYMBOL(mmz_alloc);
|
||||
|
||||
void mmz_free(unsigned long long phy_addr)
|
||||
{
|
||||
mmz_mmb_freeby_phys(phy_addr);
|
||||
}
|
||||
EXPORT_SYMBOL(mmz_free);
|
||||
|
||||
void *mmz_map(unsigned long long phy_addr, unsigned long size, bool cached)
|
||||
{
|
||||
mmz_mmb_t *pmmb = NULL;
|
||||
void *vir_addr = NULL;
|
||||
unsigned long offset;
|
||||
|
||||
pmmb = mmz_mmb_getby_phys_2(phy_addr, &offset);
|
||||
if ( pmmb == NULL ) {
|
||||
osal_printk("mmz remap cache get mmz_mmb failed\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (size == 0 || size + offset > pmmb->length) {
|
||||
osal_printk("mmz remap size(0x%lx) is zero or bigger than mmb size(0x%lx)", size, pmmb->length);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ( cached == 1 ) {
|
||||
vir_addr = mmz_mmb_map2kern_cached(pmmb);
|
||||
} else {
|
||||
vir_addr = mmz_mmb_map2kern(pmmb);
|
||||
}
|
||||
if (vir_addr == NULL) {
|
||||
osal_printk("mmz remap failed!\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return vir_addr + offset;
|
||||
}
|
||||
EXPORT_SYMBOL(mmz_map);
|
||||
|
||||
void mmz_unmap(void *vir_addr)
|
||||
{
|
||||
if (vir_addr != NULL) {
|
||||
mmz_mmb_t *pmmb = mmz_mmb_getby_kvirt(vir_addr);
|
||||
|
||||
if (pmmb != NULL) {
|
||||
mmz_mmb_unmap(pmmb);
|
||||
}
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(mmz_unmap);
|
||||
|
||||
int mmz_check_phyaddr(unsigned long long phy_addr, unsigned long len)
|
||||
{
|
||||
/* if address in mmz of current system */
|
||||
if (mmz_is_phys_in_mmz(phy_addr, len))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(mmz_check_phyaddr);
|
||||
|
||||
int mmz_flush_cache(unsigned long phy_addr, void *kvirt, unsigned long length)
|
||||
{
|
||||
mmz_mmb_t *pmmb = NULL;
|
||||
unsigned long offset;
|
||||
|
||||
/*err address flush maybe panic so judge input parameter*/
|
||||
pmmb = mmz_mmb_getby_phys_2(phy_addr, &offset);
|
||||
if ( pmmb == NULL ) {
|
||||
osal_printk("mmz flush cache get mmz_mmb failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( mmz_mmb_flush_dcache_byaddr(kvirt, phy_addr, length) != 0 )
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(mmz_flush_cache);
|
||||
+956
@@ -0,0 +1,956 @@
|
||||
/*
|
||||
* Copyright (c) XMEDIA. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <generated/autoconf.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/fcntl.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/mman.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/version.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#ifndef CONFIG_64BIT
|
||||
#include <linux/highmem.h>
|
||||
#include <asm/pgtable.h>
|
||||
#endif
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
|
||||
#include "osal.h"
|
||||
#include "allocator.h"
|
||||
#include "version.h"
|
||||
#include <linux/lotus/kapi.h>
|
||||
|
||||
|
||||
OSAL_LIST_HEAD(mmz_list);
|
||||
|
||||
static DEFINE_SEMAPHORE(mmz_lock);
|
||||
|
||||
#define MMZ_SETUP_CMDLINE_LEN 256
|
||||
#define MMZ_ALLOCATOR_NAME_LEN 32
|
||||
#define MMZ_DEFAULT_ALLOCATOR "xmedia"
|
||||
#ifndef MODULE
|
||||
|
||||
static char setup_zones[MMZ_SETUP_CMDLINE_LEN] = {'\0'};
|
||||
static int __init parse_kern_mmz(char *line)
|
||||
{
|
||||
strlcpy(setup_zones, line, sizeof(setup_zones));
|
||||
|
||||
return 1;
|
||||
}
|
||||
__setup("mmz=", parse_kern_mmz);
|
||||
|
||||
static char setup_allocator[MMZ_ALLOCATOR_NAME_LEN] = MMZ_DEFAULT_ALLOCATOR;
|
||||
static int __init parse_kern_allocator(char *line)
|
||||
{
|
||||
strlcpy(setup_allocator, line, sizeof(setup_allocator));
|
||||
return 1;
|
||||
}
|
||||
__setup("mmz_allocator=", parse_kern_allocator);
|
||||
|
||||
#else
|
||||
static char setup_zones[MMZ_SETUP_CMDLINE_LEN]={'\0'};
|
||||
static char setup_allocator[MMZ_ALLOCATOR_NAME_LEN] = MMZ_DEFAULT_ALLOCATOR; //default setting
|
||||
module_param_string(mmz, setup_zones, MMZ_SETUP_CMDLINE_LEN, 0600);
|
||||
module_param_string(mmz_allocator, setup_allocator, MMZ_ALLOCATOR_NAME_LEN, 0600);
|
||||
MODULE_PARM_DESC(mmz,"mmz_allocator=allocator mmz=name,0,start,size,type,eqsize:[others] map_mmz=start,size:[others]");
|
||||
#endif
|
||||
|
||||
static struct mmz_allocator the_allocator;
|
||||
|
||||
mmz_mmz_t *mmz_mmz_create(const char *name,
|
||||
unsigned long gfp,
|
||||
unsigned long phys_start,
|
||||
unsigned long nbytes)
|
||||
{
|
||||
mmz_mmz_t *p = NULL;
|
||||
|
||||
mmz_trace_func();
|
||||
|
||||
if(name == NULL) {
|
||||
printk(KERN_ERR "%s: 'name' should not be NULL!", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
p = kmalloc(sizeof(mmz_mmz_t) + 1, GFP_KERNEL);
|
||||
if (p == NULL) {
|
||||
printk(KERN_ERR "%s: System OOM!\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(p, 0, sizeof(mmz_mmz_t)+1);
|
||||
strlcpy(p->name, name, MMZ_MMZ_NAME_LEN);
|
||||
p->gfp = gfp;
|
||||
p->phys_start = phys_start;
|
||||
p->nbytes = nbytes;
|
||||
|
||||
OSAL_INIT_LIST_HEAD(&p->list);
|
||||
OSAL_INIT_LIST_HEAD(&p->mmb_list);
|
||||
|
||||
p->destructor = kfree;
|
||||
|
||||
return p;
|
||||
}
|
||||
EXPORT_SYMBOL(mmz_mmz_create);
|
||||
|
||||
int mmz_mmz_destroy(mmz_mmz_t *zone)
|
||||
{
|
||||
if(zone == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(zone->destructor) {
|
||||
zone->destructor(zone);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(mmz_mmz_destroy);
|
||||
|
||||
static int _check_mmz(mmz_mmz_t *zone)
|
||||
{
|
||||
mmz_mmz_t *p = NULL;
|
||||
|
||||
unsigned long new_start=zone->phys_start;
|
||||
unsigned long new_end=zone->phys_start+zone->nbytes;
|
||||
|
||||
if (zone->nbytes == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!((new_start >= __pa((uintptr_t)high_memory)) ||
|
||||
((new_start < PHYS_OFFSET) && (new_end <= PHYS_OFFSET)))) {
|
||||
printk(KERN_ERR "ERROR: Conflict MMZ:\n");
|
||||
printk(KERN_ERR MMZ_MMZ_FMT_S "\n", mmz_mmz_fmt_arg(zone));
|
||||
printk(KERN_ERR "MMZ conflict to kernel memory (0x%08lX, 0x%08lX)\n",
|
||||
(long unsigned int)PHYS_OFFSET,
|
||||
(long unsigned int)(__pa((uintptr_t)high_memory) - 1));
|
||||
return -1;
|
||||
}
|
||||
|
||||
osal_list_for_each_entry(p, &mmz_list, list) {
|
||||
unsigned long start, end;
|
||||
start = p->phys_start;
|
||||
end = p->phys_start + p->nbytes;
|
||||
|
||||
if(new_start >= end) {
|
||||
continue;
|
||||
} else if (new_start < start && new_end <= start) {
|
||||
continue;
|
||||
} else {
|
||||
;
|
||||
}
|
||||
|
||||
printk(KERN_ERR "ERROR: Conflict MMZ:\n");
|
||||
printk(KERN_ERR "MMZ new: " MMZ_MMZ_FMT_S "\n", mmz_mmz_fmt_arg(zone));
|
||||
printk(KERN_ERR "MMZ exist: " MMZ_MMZ_FMT_S "\n", mmz_mmz_fmt_arg(p));
|
||||
printk(KERN_ERR "Add new MMZ failed!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mmz_mmz_register(mmz_mmz_t *zone)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
mmz_trace(1, MMZ_MMZ_FMT_S, mmz_mmz_fmt_arg(zone));
|
||||
|
||||
if(zone == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
down(&mmz_lock);
|
||||
|
||||
if (0 == strcmp(setup_allocator, "xmedia")) {
|
||||
ret = _check_mmz(zone);
|
||||
if (ret) {
|
||||
up(&mmz_lock);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
OSAL_INIT_LIST_HEAD(&zone->mmb_list);
|
||||
|
||||
osal_list_add(&zone->list, &mmz_list);
|
||||
|
||||
up(&mmz_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mmz_mmz_unregister(mmz_mmz_t *zone)
|
||||
{
|
||||
int losts = 0;
|
||||
mmz_mmb_t *p = NULL;
|
||||
|
||||
if(zone == NULL)
|
||||
return -1;
|
||||
|
||||
mmz_trace_func();
|
||||
|
||||
down(&mmz_lock);
|
||||
osal_list_for_each_entry(p, &zone->mmb_list, list) {
|
||||
printk(KERN_WARNING "MB Lost: " MMZ_MMB_FMT_S "\n",
|
||||
mmz_mmb_fmt_arg(p));
|
||||
losts++;
|
||||
}
|
||||
|
||||
if (losts) {
|
||||
printk(KERN_ERR "%d mmbs not free, mmz<%s> can not be unregistered!\n",
|
||||
losts, zone->name);
|
||||
up(&mmz_lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
osal_list_del(&zone->list);
|
||||
up(&mmz_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
mmz_mmb_t *mmz_mmb_alloc(const char *name,
|
||||
unsigned long size,
|
||||
unsigned long align,
|
||||
unsigned long gfp,
|
||||
const char *mmz_name)
|
||||
{
|
||||
mmz_mmb_t *mmb = NULL;
|
||||
|
||||
down(&mmz_lock);
|
||||
mmb = the_allocator.mmb_alloc(name, size, align, gfp, mmz_name, NULL);
|
||||
up(&mmz_lock);
|
||||
|
||||
return mmb;
|
||||
}
|
||||
EXPORT_SYMBOL(mmz_mmb_alloc);
|
||||
|
||||
void *mmz_mmb_map2kern(mmz_mmb_t *mmb)
|
||||
{
|
||||
void *p = NULL;
|
||||
|
||||
if(mmb == NULL)
|
||||
return NULL;
|
||||
|
||||
down(&mmz_lock);
|
||||
p = the_allocator.mmb_map2kern(mmb, 0);
|
||||
up(&mmz_lock);
|
||||
|
||||
return p;
|
||||
}
|
||||
EXPORT_SYMBOL(mmz_mmb_map2kern);
|
||||
|
||||
/* mmf: media-memory fragment */
|
||||
void *mmz_mmf_map2kern_nocache(unsigned long phys, int len)
|
||||
{
|
||||
void *virt = the_allocator.mmf_map(phys, len, 0);
|
||||
if (virt != NULL)
|
||||
return virt;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(mmz_mmf_map2kern_nocache);
|
||||
|
||||
void *mmz_mmf_map2kern_cache(unsigned long phys, int len)
|
||||
{
|
||||
void *virt = the_allocator.mmf_map(phys, len, 1);
|
||||
if (virt != NULL)
|
||||
return virt;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(mmz_mmf_map2kern_cache);
|
||||
|
||||
void mmz_mmf_unmap(void *virt)
|
||||
{
|
||||
the_allocator.mmf_unmap(virt);
|
||||
}
|
||||
EXPORT_SYMBOL(mmz_mmf_unmap);
|
||||
|
||||
void *mmz_mmb_map2kern_cached(mmz_mmb_t *mmb)
|
||||
{
|
||||
void *p = NULL;
|
||||
|
||||
if(mmb == NULL)
|
||||
return NULL;
|
||||
|
||||
down(&mmz_lock);
|
||||
p = the_allocator.mmb_map2kern(mmb, 1);
|
||||
up(&mmz_lock);
|
||||
|
||||
return p;
|
||||
}
|
||||
EXPORT_SYMBOL(mmz_mmb_map2kern_cached);
|
||||
|
||||
int mmz_mmb_flush_dcache_byaddr(void *kvirt,
|
||||
unsigned long phys_addr,
|
||||
unsigned long length)
|
||||
{
|
||||
if (kvirt == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Use flush range to instead flush_cache_all,
|
||||
* because flush_cache_all only flush local cpu.
|
||||
* And on_each_cpu macro cannot used to flush
|
||||
* all cpus with irq disabled.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
__flush_dcache_area(kvirt, length);
|
||||
#else
|
||||
/*
|
||||
* dmac_map_area is invalid in kernel,
|
||||
* arm9 is not supported yet
|
||||
*/
|
||||
__cpuc_flush_dcache_area(kvirt, length);
|
||||
#endif
|
||||
#if defined(CONFIG_CACHE_L2V200) || defined(CONFIG_CACHE_L2X0)
|
||||
/* flush l2 cache, use paddr */
|
||||
/*
|
||||
* if length > L2 cache size, then this interface
|
||||
* will call <outer_flush_all>
|
||||
*/
|
||||
outer_flush_range(phys_addr, phys_addr + length);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(mmz_mmb_flush_dcache_byaddr);
|
||||
|
||||
int mmz_mmb_invalid_cache_byaddr(void *kvirt,
|
||||
unsigned long phys_addr,
|
||||
unsigned long length)
|
||||
{
|
||||
if (kvirt == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
__flush_dcache_area(kvirt, length);
|
||||
#else
|
||||
/*
|
||||
* dmac_map_area is invalid in kernel,
|
||||
* arm9 is not supported yet
|
||||
*/
|
||||
__cpuc_flush_dcache_area(kvirt, length);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(mmz_mmb_invalid_cache_byaddr);
|
||||
|
||||
int mmz_mmb_unmap(mmz_mmb_t *mmb)
|
||||
{
|
||||
int ref;
|
||||
|
||||
if(mmb == NULL)
|
||||
return -1;
|
||||
|
||||
down(&mmz_lock);
|
||||
|
||||
ref = the_allocator.mmb_unmap(mmb);
|
||||
|
||||
up(&mmz_lock);
|
||||
|
||||
return ref;
|
||||
}
|
||||
EXPORT_SYMBOL(mmz_mmb_unmap);
|
||||
|
||||
int mmz_mmb_get(mmz_mmb_t *mmb)
|
||||
{
|
||||
int ref;
|
||||
|
||||
if(mmb == NULL)
|
||||
return -1;
|
||||
|
||||
down(&mmz_lock);
|
||||
|
||||
if(mmb->flags & MMZ_MMB_RELEASED)
|
||||
printk(KERN_WARNING "mmz_mmb_get: amazing, mmb<%s> is released!\n", mmb->name);
|
||||
ref = ++mmb->phy_ref;
|
||||
|
||||
up(&mmz_lock);
|
||||
|
||||
return ref;
|
||||
}
|
||||
|
||||
int mmz_mmb_put(mmz_mmb_t *mmb)
|
||||
{
|
||||
int ref;
|
||||
|
||||
if(mmb == NULL)
|
||||
return -1;
|
||||
|
||||
down(&mmz_lock);
|
||||
|
||||
if(mmb->flags & MMZ_MMB_RELEASED)
|
||||
printk(KERN_WARNING "mmz_mmb_put: amazing, mmb<%s> is released!\n", mmb->name);
|
||||
|
||||
ref = --mmb->phy_ref;
|
||||
|
||||
if ((mmb->flags & MMZ_MMB_RELEASED) && (mmb->phy_ref ==0) && (mmb->map_ref ==0)) {
|
||||
the_allocator.mmb_free(mmb);
|
||||
}
|
||||
|
||||
up(&mmz_lock);
|
||||
|
||||
return ref;
|
||||
}
|
||||
|
||||
int mmz_mmb_free(mmz_mmb_t *mmb)
|
||||
{
|
||||
mmz_trace_func();
|
||||
|
||||
if(mmb == NULL)
|
||||
return -1;
|
||||
|
||||
mmz_trace(1,MMZ_MMB_FMT_S,mmz_mmb_fmt_arg(mmb));
|
||||
down(&mmz_lock);
|
||||
|
||||
if(mmb->flags & MMZ_MMB_RELEASED) {
|
||||
printk(KERN_WARNING "mmz_mmb_free: amazing, mmb<%s> has been released,\
|
||||
but is still in use!\n", mmb->name);
|
||||
up(&mmz_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (mmb->phy_ref > 0) {
|
||||
printk(KERN_WARNING "mmz_mmb_free: free mmb<%s> delayed \
|
||||
for which ref-count is %d!\n",
|
||||
mmb->name, mmb->map_ref);
|
||||
mmb->flags |= MMZ_MMB_RELEASED;
|
||||
up(&mmz_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (mmb->flags & MMZ_MMB_MAP2KERN) {
|
||||
printk(KERN_WARNING "mmz_mmb_free: free mmb<%s> delayed for which \
|
||||
is kernel-mapped to 0x%pK with map_ref %d!\n",
|
||||
mmb->name, mmb->kvirt, mmb->map_ref);
|
||||
mmb->flags |= MMZ_MMB_RELEASED;
|
||||
up(&mmz_lock);
|
||||
return 0;
|
||||
}
|
||||
the_allocator.mmb_free(mmb);
|
||||
up(&mmz_lock);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(mmz_mmb_free);
|
||||
|
||||
#define MACH_MMB(p, val, member) do {\
|
||||
mmz_mmz_t *__mach_mmb_zone__ = NULL; \
|
||||
(p) = NULL;\
|
||||
list_for_each_entry(__mach_mmb_zone__, &mmz_list, list) { \
|
||||
mmz_mmb_t *__mach_mmb__ = NULL;\
|
||||
list_for_each_entry(__mach_mmb__, &__mach_mmb_zone__->mmb_list, list) { \
|
||||
if (__mach_mmb__->member == (val)) { \
|
||||
(p) = __mach_mmb__; \
|
||||
break;\
|
||||
} \
|
||||
} \
|
||||
if (p != NULL)break;\
|
||||
} \
|
||||
}while(0)
|
||||
|
||||
mmz_mmb_t *mmz_mmb_getby_phys(unsigned long addr)
|
||||
{
|
||||
mmz_mmb_t *p = NULL;
|
||||
down(&mmz_lock);
|
||||
MACH_MMB(p, addr, phys_addr);
|
||||
up(&mmz_lock);
|
||||
return p;
|
||||
}
|
||||
EXPORT_SYMBOL(mmz_mmb_getby_phys);
|
||||
|
||||
unsigned long usr_virt_to_phys(unsigned long virt)
|
||||
{
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0)
|
||||
pgd_t* pgd = NULL;
|
||||
pud_t* pud = NULL;
|
||||
#endif
|
||||
pmd_t* pmd = NULL;
|
||||
pte_t* pte = NULL;
|
||||
unsigned int cacheable = 0;
|
||||
unsigned long page_addr = 0;
|
||||
unsigned long page_offset = 0;
|
||||
unsigned long phys_addr = 0;
|
||||
|
||||
if (virt & 0x3) {
|
||||
printk("invalid virt addr 0x%08lx[not 4 bytes align]\n", virt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (virt >= PAGE_OFFSET) {
|
||||
printk("invalid user space virt addr 0x%08lx\n", virt);
|
||||
return 0;
|
||||
}
|
||||
// in kernel 5.10 just use pmd_off is ok
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0)
|
||||
pgd = pgd_offset(current->mm, virt);
|
||||
|
||||
if (pgd_none(*pgd)) {
|
||||
printk("printk: not mapped in pgd!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
pud = pud_offset(pgd, virt);
|
||||
|
||||
if (pud_none(*pud)) {
|
||||
printk("printk: not mapped in pud!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
pmd = pmd_offset(pud, virt);
|
||||
#else
|
||||
pmd = pmd_off(current->mm, virt);
|
||||
#endif
|
||||
if (pmd_none(*pmd)) {
|
||||
printk("printk: not mapped in pmd!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
pte = pte_offset_map(pmd, virt);
|
||||
|
||||
if (pte_none(*pte)) {
|
||||
printk("printk: not mapped in pte!\n");
|
||||
pte_unmap(pte);
|
||||
return 0;
|
||||
}
|
||||
|
||||
page_addr = (pte_val(*pte) & PHYS_MASK) & PAGE_MASK;
|
||||
page_offset = virt & ~PAGE_MASK;
|
||||
phys_addr = page_addr | page_offset;
|
||||
#ifdef CONFIG_64BIT
|
||||
if (pte_val(*pte) & (1 << 4))
|
||||
#else
|
||||
if (pte_val(*pte) & (1 << 3))
|
||||
#endif
|
||||
{ cacheable = 1; }
|
||||
|
||||
/*
|
||||
* phys_addr: the lowest bit indicates its cache attribute
|
||||
* 1: cacheable
|
||||
* 0: uncacheable
|
||||
*/
|
||||
phys_addr |= cacheable;
|
||||
|
||||
pte_unmap(pte);
|
||||
|
||||
return phys_addr;
|
||||
}
|
||||
EXPORT_SYMBOL(usr_virt_to_phys);
|
||||
|
||||
#define MACH_MMB_2(p, val, member, Outoffset) do {\
|
||||
mmz_mmz_t *__mach_mmb_zone__ = NULL; \
|
||||
(p) = NULL;\
|
||||
list_for_each_entry(__mach_mmb_zone__, &mmz_list, list) { \
|
||||
mmz_mmb_t *__mach_mmb__ = NULL;\
|
||||
list_for_each_entry(__mach_mmb__, &__mach_mmb_zone__->mmb_list, list) { \
|
||||
if ((__mach_mmb__->member <= (val)) && ((__mach_mmb__->length + __mach_mmb__->member) > (val))) { \
|
||||
(p) = __mach_mmb__; \
|
||||
Outoffset = val - __mach_mmb__->member;\
|
||||
break;\
|
||||
}\
|
||||
} \
|
||||
if (p != NULL)break;\
|
||||
} \
|
||||
}while(0)
|
||||
|
||||
|
||||
mmz_mmb_t *mmz_mmb_getby_kvirt(void *virt)
|
||||
{
|
||||
mmz_mmb_t *p = NULL;
|
||||
unsigned long Outoffset;
|
||||
|
||||
if (virt == NULL)
|
||||
return NULL;
|
||||
|
||||
down(&mmz_lock);
|
||||
MACH_MMB_2(p, virt, kvirt, Outoffset);
|
||||
up(&mmz_lock);
|
||||
|
||||
mmz_trace(1, "Outoffset %lu \n", Outoffset);
|
||||
|
||||
return p;
|
||||
}
|
||||
EXPORT_SYMBOL(mmz_mmb_getby_kvirt);
|
||||
|
||||
mmz_mmb_t *mmz_mmb_getby_phys_2(unsigned long addr, unsigned long *Outoffset)
|
||||
{
|
||||
mmz_mmb_t *p = NULL;
|
||||
|
||||
down(&mmz_lock);
|
||||
MACH_MMB_2(p, addr, phys_addr, *Outoffset);
|
||||
up(&mmz_lock);
|
||||
return p;
|
||||
}
|
||||
EXPORT_SYMBOL(mmz_mmb_getby_phys_2);
|
||||
|
||||
mmz_mmz_t *mmz_mmz_find(unsigned long gfp, const char *mmz_name)
|
||||
{
|
||||
mmz_mmz_t *p = NULL;
|
||||
|
||||
down(&mmz_lock);
|
||||
begin_list_for_each_mmz(p, gfp, mmz_name)
|
||||
up(&mmz_lock);
|
||||
return p;
|
||||
end_list_for_each_mmz()
|
||||
up(&mmz_lock);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(mmz_mmz_find);
|
||||
|
||||
unsigned long mmz_mmz_get_phys(const char *zone_name)
|
||||
{
|
||||
mmz_mmz_t *zone = NULL;
|
||||
|
||||
zone = mmz_mmz_find(0, zone_name);
|
||||
if (zone != NULL)
|
||||
return zone->phys_start;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(mmz_mmz_get_phys);
|
||||
|
||||
int mmz_map_mmz_unregister(mmz_mmz_t *zone)
|
||||
{
|
||||
int losts = 0;
|
||||
mmz_mmb_t *p = NULL;
|
||||
|
||||
if (zone == NULL)
|
||||
return -1;
|
||||
|
||||
mmz_trace_func();
|
||||
|
||||
down(&mmz_lock);
|
||||
osal_list_for_each_entry(p, &zone->mmb_list, list) {
|
||||
printk(KERN_WARNING "MB Lost: " MMZ_MMB_FMT_S "\n",
|
||||
mmz_mmb_fmt_arg(p));
|
||||
losts++;
|
||||
}
|
||||
|
||||
if (losts) {
|
||||
printk(KERN_ERR "%d mmbs not free, mmz<%s> can not be unregistered!\n",
|
||||
losts, zone->name);
|
||||
up(&mmz_lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
osal_list_del(&zone->list);
|
||||
up(&mmz_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mmz_vma_check(unsigned long vm_start, unsigned long vm_end)
|
||||
{
|
||||
struct vm_area_struct *pvma1;
|
||||
struct vm_area_struct *pvma2;
|
||||
|
||||
pvma1 = find_vma(current->mm, vm_start);
|
||||
if (pvma1 == NULL) {
|
||||
printk(KERN_ERR "ERROR: pvma1 is null\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
pvma2 = find_vma(current->mm, vm_end-1);
|
||||
if (pvma2 == NULL) {
|
||||
printk(KERN_ERR "ERROR: pvma2 is null\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pvma1 != pvma2) {
|
||||
printk(KERN_ERR "ERROR: pvma1:[0x%lx,0x%lx) and pvma2:[0x%lx,0x%lx) are not equal\n",
|
||||
pvma1->vm_start, pvma1->vm_end, pvma2->vm_start, pvma2->vm_end);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!(pvma1->vm_flags & VM_WRITE)) {
|
||||
printk(KERN_ERR "ERROR vma flag:0x%lx\n", pvma1->vm_flags);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pvma1->vm_start > vm_start) {
|
||||
printk("cannot find corresponding vma, vm[%lx, %lx], user range[%lx,%lx]\n", pvma1->vm_start, pvma1->vm_end, vm_start, vm_end);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(mmz_vma_check);
|
||||
|
||||
int mmz_is_phys_in_mmz(unsigned long addr_start, unsigned long addr_len)
|
||||
{
|
||||
mmz_mmz_t *p = NULL;
|
||||
unsigned long addr_end = addr_start + addr_len;
|
||||
unsigned long temp_start, temp_end;
|
||||
|
||||
osal_list_for_each_entry(p, &mmz_list, list) {
|
||||
temp_start = p->phys_start;
|
||||
temp_end = p->phys_start + p->nbytes;
|
||||
if ((addr_start >= temp_start) && (addr_end <= temp_end)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
EXPORT_SYMBOL(mmz_is_phys_in_mmz);
|
||||
|
||||
|
||||
int mmz_mmb_flush_dcache_byaddr_safe(void *kvirt,
|
||||
unsigned long phys_addr,
|
||||
unsigned long length)
|
||||
{
|
||||
int ret = 0;
|
||||
struct mm_struct *mm = current->mm;
|
||||
|
||||
if (kvirt == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0)
|
||||
down_read(&mm->mmap_sem);
|
||||
#else
|
||||
down_read(&mm->mmap_lock);
|
||||
#endif
|
||||
if (mmz_vma_check((unsigned long)(uintptr_t)kvirt, (unsigned long)(uintptr_t)kvirt+length)) {
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0)
|
||||
up_read(&mm->mmap_sem);
|
||||
#else
|
||||
up_read(&mm->mmap_lock);
|
||||
#endif
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
ret = mmz_mmb_flush_dcache_byaddr(kvirt, phys_addr, length);
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0)
|
||||
up_read(&mm->mmap_sem);
|
||||
#else
|
||||
up_read(&mm->mmap_lock);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(mmz_mmb_flush_dcache_byaddr_safe);
|
||||
|
||||
#define MEDIA_MEM_NAME "media-mem"
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
static void mmz_proc_version(struct osal_proc_dir_entry *sfile)
|
||||
{
|
||||
unsigned char mmz_version[128] = {0};
|
||||
VERSION_FORMAT(mmz_version, "MMZ", "V1.0", "");
|
||||
osal_seq_printf(sfile, "\n%s\n\n", mmz_version);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int mmz_seq_show(struct osal_proc_dir_entry *sfile)
|
||||
{
|
||||
mmz_mmz_t *p = NULL;
|
||||
int len = 0;
|
||||
unsigned int zone_number = 0;
|
||||
unsigned int block_number = 0;
|
||||
unsigned int used_size = 0;
|
||||
unsigned int free_size = 0;
|
||||
unsigned int mmz_total_size = 0;
|
||||
|
||||
mmz_trace_func();
|
||||
|
||||
mmz_proc_version(sfile);
|
||||
|
||||
down(&mmz_lock);
|
||||
list_for_each_entry(p, &mmz_list, list) {
|
||||
mmz_mmb_t *mmb = NULL;
|
||||
osal_seq_printf(sfile, "+---ZONE: " MMZ_MMZ_FMT_S "\n", mmz_mmz_fmt_arg(p));
|
||||
mmz_total_size += p->nbytes / 1024;
|
||||
++zone_number;
|
||||
|
||||
list_for_each_entry(mmb, &p->mmb_list, list) {
|
||||
osal_seq_printf(sfile, " |-MMB: " MMZ_MMB_FMT_S "\n", mmz_mmb_fmt_arg(mmb));
|
||||
used_size += mmb->length / 1024;
|
||||
++block_number;
|
||||
}
|
||||
}
|
||||
|
||||
if (mmz_total_size != 0) {
|
||||
free_size = mmz_total_size - used_size;
|
||||
osal_seq_printf(sfile, "\n---MMZ_USE_INFO:\n total size=%dKB(%dMB),"
|
||||
"used=%dKB(%dMB + %dKB),free=%dKB(%dMB + %dKB),"
|
||||
"zone_number=%d,block_number=%d\n",
|
||||
mmz_total_size, mmz_total_size / 1024,
|
||||
used_size, used_size / 1024, used_size % 1024,
|
||||
free_size, free_size / 1024, free_size % 1024,
|
||||
zone_number, block_number);
|
||||
}
|
||||
up(&mmz_lock);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static int __init media_mem_proc_init(void)
|
||||
{
|
||||
osal_proc_entry_t *proc = NULL;
|
||||
|
||||
proc = osal_create_proc_entry(MEDIA_MEM_NAME, NULL);
|
||||
if (proc == NULL) {
|
||||
printk(KERN_ERR "Create mmz proc fail!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
proc->read = mmz_seq_show;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit media_mem_proc_exit(void)
|
||||
{
|
||||
osal_remove_proc_entry(MEDIA_MEM_NAME, NULL);
|
||||
}
|
||||
|
||||
#else
|
||||
static int __init media_mem_proc_init(void) { return 0; }
|
||||
static void __exit media_mem_proc_exit(void) { }
|
||||
|
||||
#endif /* CONFIG_PROC_FS */
|
||||
|
||||
static void mmz_exit_check(void)
|
||||
{
|
||||
mmz_mmz_t* pmmz = NULL;
|
||||
struct osal_list_head* p = NULL, *n = NULL;
|
||||
|
||||
mmz_trace_func();
|
||||
|
||||
list_for_each_safe(p, n, &mmz_list) {
|
||||
pmmz = list_entry(p,mmz_mmz_t,list);
|
||||
printk(KERN_WARNING "MMZ force removed: " MMZ_MMZ_FMT_S "\n",
|
||||
mmz_mmz_fmt_arg(pmmz));
|
||||
mmz_mmz_unregister(pmmz);
|
||||
mmz_mmz_destroy(pmmz);
|
||||
}
|
||||
}
|
||||
|
||||
int __init media_mem_init(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
printk(KERN_INFO "Media Memory Zone Manager\n");
|
||||
|
||||
if (setup_zones[0] == '\0') {
|
||||
char *boot_mmz_para_start = NULL;
|
||||
char *boot_mmz_para_end = NULL;
|
||||
int mmz_para_len = 0;
|
||||
|
||||
/* get parameter from bootargs*/
|
||||
boot_mmz_para_start = lotus_get_cmd_line();
|
||||
|
||||
if (boot_mmz_para_start != NULL)
|
||||
boot_mmz_para_start = strstr(boot_mmz_para_start, "mmz_allocator=");
|
||||
|
||||
printk("mmz allocator from bootargs:%s\n", boot_mmz_para_start == NULL ? "none" : boot_mmz_para_start);
|
||||
if (boot_mmz_para_start != NULL) {
|
||||
|
||||
boot_mmz_para_start += strlen("mmz_allocator=");
|
||||
|
||||
/*find mmz parameter end*/
|
||||
boot_mmz_para_end = strchr(boot_mmz_para_start, ' ');
|
||||
|
||||
/*if this is the last bootargs, bootargs end is mmz parameter end*/
|
||||
if (boot_mmz_para_end == NULL) {
|
||||
mmz_para_len = strlen(boot_mmz_para_start);
|
||||
} else {
|
||||
mmz_para_len = boot_mmz_para_end - boot_mmz_para_start;
|
||||
}
|
||||
|
||||
mmz_para_len = ((mmz_para_len > MMZ_ALLOCATOR_NAME_LEN) ? MMZ_ALLOCATOR_NAME_LEN : mmz_para_len);
|
||||
memcpy(setup_allocator, boot_mmz_para_start, mmz_para_len);
|
||||
|
||||
boot_mmz_para_start = lotus_get_cmd_line();
|
||||
/*no need judge here*/
|
||||
boot_mmz_para_start = strstr(boot_mmz_para_start, "mmz=") + strlen("mmz=");
|
||||
|
||||
printk("mmz zone setting from bootargs:%s\n", boot_mmz_para_start);
|
||||
if (boot_mmz_para_start != NULL) {
|
||||
|
||||
/*find mmz parameter end*/
|
||||
boot_mmz_para_end = strchr(boot_mmz_para_start, ' ');
|
||||
|
||||
/*if this is the last bootargs, bootargs end is mmz parameter end*/
|
||||
if (boot_mmz_para_end == NULL) {
|
||||
mmz_para_len = strlen(boot_mmz_para_start);
|
||||
} else {
|
||||
mmz_para_len = boot_mmz_para_end - boot_mmz_para_start;
|
||||
}
|
||||
|
||||
mmz_para_len = ((mmz_para_len > MMZ_SETUP_CMDLINE_LEN) ? MMZ_SETUP_CMDLINE_LEN : mmz_para_len);
|
||||
memcpy(setup_zones, boot_mmz_para_start, mmz_para_len);
|
||||
printk("mmz cfg from bootargs allocator:%s zones:%s\n", setup_allocator, setup_zones);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (strcmp(setup_allocator, "cma") == 0) {
|
||||
#ifdef CONFIG_CMA
|
||||
ret = cma_allocator_setopt(&the_allocator);
|
||||
#else
|
||||
pr_err("cma is not enabled in kernel, please check!\n");
|
||||
return -EINVAL;
|
||||
#endif
|
||||
} else if (strcmp(setup_allocator, "xmedia") == 0) {
|
||||
ret = allocator_setopt(&the_allocator);
|
||||
} else {
|
||||
printk("The module param \"setup_allocator\" should be \"cma\" or \"xmedia\", which is \"%s\"\n",
|
||||
setup_allocator);
|
||||
mmz_exit_check();
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = the_allocator.init(setup_zones);
|
||||
if (ret != 0) {
|
||||
mmz_exit_check();
|
||||
return ret;
|
||||
}
|
||||
|
||||
media_mem_proc_init();
|
||||
mmz_userdev_init();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __exit media_mem_exit(void)
|
||||
{
|
||||
mmz_userdev_exit();
|
||||
mmz_exit_check();
|
||||
media_mem_proc_exit();
|
||||
}
|
||||
|
||||
/*
|
||||
module_init(media_mem_init);
|
||||
module_exit(media_mem_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
*/
|
||||
/*
|
||||
#ifndef MODULE
|
||||
subsys_initcall(media_mem_init);
|
||||
#endif
|
||||
*/
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (c) XMEDIA. All rights reserved.
|
||||
*/
|
||||
#ifndef __MMZ_ARCH_OPS_HEADER__
|
||||
#define __MMZ_ARCH_OPS_HEADER__
|
||||
|
||||
#if defined(CONFIG_ARM64)
|
||||
/* this function is used to change memory's property. */
|
||||
static void dma_pages_remap(struct page *page, size_t size, pgprot_t prot) {}
|
||||
|
||||
static void dma_buffer_clear(struct page *page, size_t size)
|
||||
{
|
||||
memset(page_address(page), 0, size);
|
||||
__flush_dcache_area(page_address(page), size);
|
||||
}
|
||||
|
||||
static void mmb_dcache_flush(mmz_mmb_t *mmb)
|
||||
{
|
||||
__flush_dcache_area((void *)mmb->kvirt, (size_t)mmb->length);
|
||||
}
|
||||
|
||||
static pgprot_t arch_kern_pgprot(int cache)
|
||||
{
|
||||
if (cache) {
|
||||
return PAGE_KERNEL;
|
||||
}
|
||||
|
||||
return __pgprot(PROT_NORMAL_NC);
|
||||
}
|
||||
|
||||
#elif defined(CONFIG_ARM)
|
||||
#include <asm/highmem.h>
|
||||
#include <asm/pgtable.h>
|
||||
|
||||
extern void __dma_clear_buffer(struct page *page, size_t size);
|
||||
|
||||
static void dma_buffer_clear(struct page *page, size_t size)
|
||||
{
|
||||
__dma_clear_buffer(page, size);
|
||||
}
|
||||
|
||||
static void mmb_dcache_flush(mmz_mmb_t *mmb)
|
||||
{
|
||||
__cpuc_flush_dcache_area((void *)mmb->kvirt, (size_t)mmb->length);
|
||||
|
||||
outer_flush_range(mmb->phys_addr, mmb->phys_addr + mmb->length);
|
||||
}
|
||||
|
||||
static pgprot_t arch_kern_pgprot(int cache)
|
||||
{
|
||||
if (cache) {
|
||||
return pgprot_kernel;
|
||||
}
|
||||
|
||||
return pgprot_noncached(pgprot_kernel);
|
||||
}
|
||||
|
||||
#else
|
||||
#error no proper arch selected(CONFIG_ARM64/CONFIG_ARM)!
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (c) XMEDIA. All rights reserved.
|
||||
*/
|
||||
#include "osal.h"
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)
|
||||
|
||||
#ifndef CONFIG_64BIT
|
||||
#include <mach/io.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
void *osal_ioremap(unsigned long phys_addr, unsigned long size)
|
||||
{
|
||||
return ioremap(phys_addr, size);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_ioremap);
|
||||
|
||||
void *osal_ioremap_nocache(unsigned long phys_addr, unsigned long size)
|
||||
{
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0)
|
||||
return ioremap_nocache(phys_addr, size);
|
||||
#else
|
||||
return ioremap(phys_addr, size);
|
||||
#endif
|
||||
}
|
||||
EXPORT_SYMBOL(osal_ioremap_nocache);
|
||||
|
||||
void *osal_ioremap_cached(unsigned long phys_addr, unsigned long size)
|
||||
{
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0)
|
||||
return ioremap_cached(phys_addr, size);
|
||||
#else
|
||||
return ioremap_cache(phys_addr, size);
|
||||
#endif
|
||||
}
|
||||
|
||||
void *osal_ioremap_wc(unsigned long phys_addr, unsigned long size)
|
||||
{
|
||||
return ioremap_wc(phys_addr, size);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_ioremap_wc);
|
||||
|
||||
|
||||
EXPORT_SYMBOL(osal_ioremap_cached);
|
||||
|
||||
void osal_iounmap(void *addr)
|
||||
{
|
||||
iounmap(addr);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_iounmap);
|
||||
|
||||
unsigned long osal_copy_from_user(void *to, const void *from, unsigned long n)
|
||||
{
|
||||
return copy_from_user(to, from, n);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_copy_from_user);
|
||||
|
||||
unsigned long osal_copy_to_user(void *to, const void *from, unsigned long n)
|
||||
{
|
||||
return copy_to_user(to, from, n);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_copy_to_user);
|
||||
|
||||
int osal_access_ok(int type, const void *addr, unsigned long size)
|
||||
{
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0)
|
||||
return access_ok(type, addr, size);
|
||||
#else
|
||||
return access_ok(addr, size);
|
||||
#endif
|
||||
}
|
||||
EXPORT_SYMBOL(osal_access_ok);
|
||||
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright (c) XMEDIA. All rights reserved.
|
||||
*/
|
||||
#include "osal.h"
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <asm/atomic.h>
|
||||
#include <linux/printk.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
int osal_atomic_init(osal_atomic_t *atomic)
|
||||
{
|
||||
atomic_t *p = NULL;
|
||||
if (atomic == NULL) {
|
||||
osal_printk("%s - parameter invalid!\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
p = (atomic_t *)kmalloc(sizeof(atomic_t), GFP_KERNEL);
|
||||
if (p == NULL) {
|
||||
osal_printk("%s - kmalloc error!\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
memset(p, 0, sizeof(atomic_t));
|
||||
atomic->atomic = p;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(osal_atomic_init);
|
||||
|
||||
void osal_atomic_destory(osal_atomic_t *atomic)
|
||||
{
|
||||
if((atomic != NULL ) && (atomic->atomic != NULL)) {
|
||||
kfree(atomic->atomic);
|
||||
atomic->atomic = NULL;
|
||||
} else {
|
||||
osal_printk("%s - parameter invalid!\n", __FUNCTION__);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(osal_atomic_destory);
|
||||
|
||||
void osal_atomic_destroy(osal_atomic_t *atomic)
|
||||
{
|
||||
if((atomic != NULL ) && (atomic->atomic != NULL)) {
|
||||
kfree(atomic->atomic);
|
||||
atomic->atomic = NULL;
|
||||
} else {
|
||||
osal_printk("%s - parameter invalid!\n", __FUNCTION__);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(osal_atomic_destroy);
|
||||
|
||||
int osal_atomic_read(osal_atomic_t *atomic)
|
||||
{
|
||||
atomic_t *p = NULL;
|
||||
if (atomic == NULL) {
|
||||
osal_printk("%s - parameter invalid!\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
p = (atomic_t *)(atomic->atomic);
|
||||
return atomic_read(p);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_atomic_read);
|
||||
|
||||
void osal_atomic_set(osal_atomic_t *atomic, int i)
|
||||
{
|
||||
atomic_t *p = NULL;
|
||||
p = (atomic_t *)(atomic->atomic);
|
||||
atomic_set(p, i);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_atomic_set);
|
||||
|
||||
int osal_atomic_inc_return(osal_atomic_t *atomic)
|
||||
{
|
||||
atomic_t *p = NULL;
|
||||
if (atomic == NULL) {
|
||||
osal_printk("%s - parameter invalid!\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
p = (atomic_t *)(atomic->atomic);
|
||||
return atomic_inc_return(p);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_atomic_inc_return);
|
||||
|
||||
int osal_atomic_dec_return(osal_atomic_t *atomic)
|
||||
{
|
||||
atomic_t *p = NULL;
|
||||
if (atomic == NULL) {
|
||||
osal_printk("%s - parameter invalid!\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
p = (atomic_t *)(atomic->atomic);
|
||||
return atomic_dec_return(p);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_atomic_dec_return);
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (c) XMEDIA. All rights reserved.
|
||||
*/
|
||||
#include "osal.h"
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <asm/barrier.h>
|
||||
|
||||
void osal_mb(void)
|
||||
{
|
||||
mb();
|
||||
}
|
||||
EXPORT_SYMBOL(osal_mb);
|
||||
void osal_rmb(void)
|
||||
{
|
||||
rmb();
|
||||
}
|
||||
EXPORT_SYMBOL(osal_rmb);
|
||||
void osal_wmb(void)
|
||||
{
|
||||
wmb();
|
||||
}
|
||||
EXPORT_SYMBOL(osal_wmb);
|
||||
void osal_smp_mb(void)
|
||||
{
|
||||
smp_mb();
|
||||
}
|
||||
EXPORT_SYMBOL(osal_smp_mb);
|
||||
void osal_smp_rmb(void)
|
||||
{
|
||||
smp_rmb();
|
||||
}
|
||||
EXPORT_SYMBOL(osal_smp_rmb);
|
||||
void osal_smp_wmb(void)
|
||||
{
|
||||
smp_wmb();
|
||||
}
|
||||
EXPORT_SYMBOL(osal_smp_wmb);
|
||||
void osal_isb(void)
|
||||
{
|
||||
isb();
|
||||
}
|
||||
EXPORT_SYMBOL(osal_isb);
|
||||
void osal_dsb(void)
|
||||
{
|
||||
#ifdef CONFIG_64BIT
|
||||
dsb(sy);
|
||||
#else
|
||||
dsb();
|
||||
#endif
|
||||
}
|
||||
EXPORT_SYMBOL(osal_dsb);
|
||||
void osal_dmb(void)
|
||||
{
|
||||
#ifdef CONFIG_64BIT
|
||||
dmb(sy);
|
||||
#else
|
||||
dmb();
|
||||
#endif
|
||||
}
|
||||
EXPORT_SYMBOL(osal_dmb);
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (c) XMEDIA. All rights reserved.
|
||||
*/
|
||||
#include "osal.h"
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/printk.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <linux/dma-direction.h>
|
||||
#include "osal_mmz.h"
|
||||
|
||||
void osal_flush_cache_all(void)
|
||||
{
|
||||
flush_cache_all();
|
||||
}
|
||||
EXPORT_SYMBOL(osal_flush_cache_all);
|
||||
|
||||
void osal_cpuc_flush_dcache_area(void *addr, int size)
|
||||
{
|
||||
#ifdef CONFIG_64BIT
|
||||
__flush_dcache_area(addr, size);
|
||||
#else
|
||||
__cpuc_flush_dcache_area(addr, size);
|
||||
#endif
|
||||
}
|
||||
EXPORT_SYMBOL(osal_cpuc_flush_dcache_area);
|
||||
|
||||
void osal_flush_dcache_area(void *kvirt, unsigned long phys_addr, unsigned long length)
|
||||
{
|
||||
mmz_mmb_flush_dcache_byaddr(kvirt, phys_addr, length);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_flush_dcache_area);
|
||||
|
||||
int osal_flush_dcache_all(void)
|
||||
{
|
||||
#ifdef CONFIG_64BIT
|
||||
|
||||
flush_cache_all();
|
||||
|
||||
#else
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
on_each_cpu((smp_call_func_t)__cpuc_flush_kern_all, NULL, 1);
|
||||
#else
|
||||
__cpuc_flush_kern_all();
|
||||
#endif
|
||||
|
||||
outer_flush_all();
|
||||
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(osal_flush_dcache_all);
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) XMEDIA. All rights reserved.
|
||||
*/
|
||||
#include "osal.h"
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/printk.h>
|
||||
|
||||
int osal_printk(const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
int r;
|
||||
|
||||
va_start(args, fmt);
|
||||
r = vprintk(fmt, args);
|
||||
va_end(args);
|
||||
|
||||
return r;
|
||||
}
|
||||
EXPORT_SYMBOL(osal_printk);
|
||||
|
||||
void osal_panic(const char *fmt, const char *fun, int line, const char *cond)
|
||||
{
|
||||
panic(fmt, fun, line, cond);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_panic);
|
||||
@@ -0,0 +1,952 @@
|
||||
/*
|
||||
* Copyright (c) XMEDIA. All rights reserved.
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/printk.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/mm_types.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/kmod.h>
|
||||
#include <linux/devfreq.h>
|
||||
#include "media.h"
|
||||
#include "osal.h"
|
||||
#include "osal_devfreq.h"
|
||||
|
||||
#define DRVAL_DEBUG 0
|
||||
|
||||
#define GET_FILE(file) \
|
||||
do { \
|
||||
if (__get_file(file) < 0) \
|
||||
return -1; \
|
||||
} while (0)
|
||||
|
||||
#define PUT_FILE(file) \
|
||||
do { \
|
||||
if (__put_file(file) < 0) \
|
||||
return -1; \
|
||||
} while (0)
|
||||
|
||||
typedef struct osal_coat_dev {
|
||||
struct osal_dev osal_dev;
|
||||
struct media_device media_dev;
|
||||
} osal_coat_dev_t;
|
||||
|
||||
struct osal_private_data {
|
||||
struct osal_dev *dev;
|
||||
void *data;
|
||||
struct osal_poll table;
|
||||
int f_ref_cnt;
|
||||
};
|
||||
|
||||
spinlock_t f_lock;
|
||||
|
||||
void osal_device_init(void)
|
||||
{
|
||||
spin_lock_init(&f_lock);
|
||||
}
|
||||
|
||||
static int __get_file(struct file *file)
|
||||
{
|
||||
struct osal_private_data *pdata = NULL;
|
||||
|
||||
spin_lock(&f_lock);
|
||||
pdata = file->private_data;
|
||||
if (pdata == NULL) {
|
||||
spin_unlock(&f_lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
pdata->f_ref_cnt++;
|
||||
spin_unlock(&f_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __put_file(struct file *file)
|
||||
{
|
||||
struct osal_private_data *pdata = NULL;
|
||||
|
||||
spin_lock(&f_lock);
|
||||
pdata = file->private_data;
|
||||
if (pdata == NULL) {
|
||||
spin_unlock(&f_lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
pdata->f_ref_cnt--;
|
||||
spin_unlock(&f_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int osal_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct media_device *media = NULL;
|
||||
osal_coat_dev_t *coat_dev = NULL;
|
||||
struct osal_private_data *pdata = NULL;
|
||||
|
||||
if (!capable(CAP_SYS_RAWIO) || !capable(CAP_SYS_ADMIN)) {
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
// media = getmedia(inode);
|
||||
media = (struct media_device *)file->private_data;
|
||||
if (media == NULL) {
|
||||
osal_printk("%s - get media device error!\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
coat_dev = osal_container_of(media, struct osal_coat_dev, media_dev);
|
||||
pdata = (struct osal_private_data *)kmalloc(sizeof(struct osal_private_data), GFP_KERNEL);
|
||||
if (pdata == NULL) {
|
||||
osal_printk("%s - kmalloc error!\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
if (DRVAL_DEBUG) {
|
||||
osal_printk("%s - file->private_data=%pK!\n", __FUNCTION__, pdata);
|
||||
}
|
||||
|
||||
memset(pdata, 0, sizeof(struct osal_private_data));
|
||||
|
||||
file->private_data = pdata;
|
||||
pdata->dev = &(coat_dev->osal_dev);
|
||||
if (coat_dev->osal_dev.fops->open != NULL) {
|
||||
return coat_dev->osal_dev.fops->open((void *)&(pdata->data));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t osal_read(struct file *file, char __user *buf, size_t size, loff_t *offset)
|
||||
{
|
||||
struct osal_private_data *pdata = file->private_data;
|
||||
int ret = 0;
|
||||
|
||||
GET_FILE(file);
|
||||
|
||||
if (pdata->dev->fops->read != NULL) {
|
||||
ret = pdata->dev->fops->read(buf, (int)size, (long *)offset, (void *)&(pdata->data));
|
||||
}
|
||||
|
||||
PUT_FILE(file);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t osal_write(struct file *file, const char __user *buf, size_t size, loff_t *offset)
|
||||
{
|
||||
struct osal_private_data *pdata = file->private_data;
|
||||
int ret = 0;
|
||||
|
||||
GET_FILE(file);
|
||||
if (pdata->dev->fops->write != NULL) {
|
||||
ret = pdata->dev->fops->write(buf, (int)size, (long *)offset, (void *)&(pdata->data));
|
||||
}
|
||||
PUT_FILE(file);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static loff_t osal_llseek(struct file *file, loff_t offset, int whence)
|
||||
{
|
||||
struct osal_private_data *pdata = file->private_data;
|
||||
int ret = 0;
|
||||
|
||||
GET_FILE(file);
|
||||
if (DRVAL_DEBUG) {
|
||||
osal_printk("%s - file->private_data=%pK!\n", __FUNCTION__, pdata);
|
||||
}
|
||||
|
||||
if (whence == SEEK_SET) {
|
||||
if (pdata->dev->fops->llseek != NULL) {
|
||||
ret = pdata->dev->fops->llseek((long)offset, OSAL_SEEK_SET, (void *)&(pdata->data));
|
||||
}
|
||||
} else if (whence == SEEK_CUR) {
|
||||
if (pdata->dev->fops->llseek != NULL) {
|
||||
ret = pdata->dev->fops->llseek((long)offset, OSAL_SEEK_CUR, (void *)&(pdata->data));
|
||||
}
|
||||
} else if (whence == SEEK_END) {
|
||||
if (pdata->dev->fops->llseek != NULL) {
|
||||
ret = pdata->dev->fops->llseek((long)offset, OSAL_SEEK_END, (void *)&(pdata->data));
|
||||
}
|
||||
}
|
||||
|
||||
PUT_FILE(file);
|
||||
return (loff_t)ret;
|
||||
}
|
||||
|
||||
static int osal_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
int ret = 0;
|
||||
struct osal_private_data *pdata = file->private_data;
|
||||
|
||||
GET_FILE(file);
|
||||
|
||||
if (DRVAL_DEBUG) {
|
||||
osal_printk("%s - file->private_data=%pK!\n", __FUNCTION__, pdata);
|
||||
}
|
||||
|
||||
if (pdata->dev->fops->release != NULL) {
|
||||
ret = pdata->dev->fops->release((void *)&(pdata->data));
|
||||
}
|
||||
if (ret != 0) {
|
||||
PUT_FILE(file);
|
||||
osal_printk("%s - release failed!\n", __FUNCTION__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
PUT_FILE(file);
|
||||
spin_lock(&f_lock);
|
||||
if (pdata->f_ref_cnt != 0) {
|
||||
osal_printk("%s - release failed!\n", __FUNCTION__);
|
||||
spin_unlock(&f_lock);
|
||||
return -1;
|
||||
}
|
||||
kfree(file->private_data);
|
||||
file->private_data = NULL;
|
||||
spin_unlock(&f_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long __osal_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
int ret = -1;
|
||||
struct osal_private_data *pdata = file->private_data;
|
||||
char *kbuf = NULL;
|
||||
|
||||
if (DRVAL_DEBUG) {
|
||||
osal_printk("%s - file->private_data=%pK!\n", __FUNCTION__, pdata);
|
||||
}
|
||||
|
||||
if (((_IOC_SIZE(cmd) == 0) && (_IOC_DIR(cmd) != _IOC_NONE))) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((_IOC_DIR(cmd) != _IOC_NONE) && (((char *)(uintptr_t)arg) == NULL)) {
|
||||
osal_printk("%s - Input param err,it is null!\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (_IOC_DIR(cmd) == _IOC_NONE) {
|
||||
if (pdata->dev->fops->unlocked_ioctl == NULL) {
|
||||
return -1;
|
||||
} else {
|
||||
ret = pdata->dev->fops->unlocked_ioctl(cmd, arg, (void *)&(pdata->data));
|
||||
}
|
||||
} else if (_IOC_DIR(cmd) == _IOC_WRITE) {
|
||||
kbuf = (char *)vmalloc(_IOC_SIZE(cmd));
|
||||
if (kbuf == NULL) {
|
||||
osal_printk("%s - vmalloc failed!\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (copy_from_user(kbuf, (char *)(uintptr_t)arg, _IOC_SIZE(cmd))) {
|
||||
vfree(kbuf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pdata->dev->fops->unlocked_ioctl == NULL) {
|
||||
vfree(kbuf);
|
||||
return -1;
|
||||
} else {
|
||||
ret = pdata->dev->fops->unlocked_ioctl (cmd, (unsigned long)(uintptr_t)kbuf, (void *)&(pdata->data));
|
||||
}
|
||||
} else if (_IOC_DIR(cmd) == _IOC_READ) {
|
||||
kbuf = vmalloc(_IOC_SIZE(cmd));
|
||||
if (kbuf == NULL) {
|
||||
osal_printk("%s - vmalloc failed!\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
if (pdata->dev->fops->unlocked_ioctl == NULL) {
|
||||
vfree(kbuf);
|
||||
return -1;
|
||||
} else {
|
||||
ret = pdata->dev->fops->unlocked_ioctl (cmd, (unsigned long)(uintptr_t)kbuf, (void *)&(pdata->data));
|
||||
if (ret == 0) {
|
||||
if (copy_to_user((char *)(uintptr_t)arg, kbuf, _IOC_SIZE(cmd))) {
|
||||
vfree(kbuf);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (_IOC_DIR(cmd) == (_IOC_READ + _IOC_WRITE)) {
|
||||
kbuf = vmalloc(_IOC_SIZE(cmd));
|
||||
if (kbuf == NULL) {
|
||||
osal_printk("%s - vmalloc failed!\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (copy_from_user(kbuf, (char *)(uintptr_t)arg, _IOC_SIZE(cmd))) {
|
||||
vfree(kbuf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pdata->dev->fops->unlocked_ioctl == NULL) {
|
||||
vfree(kbuf);
|
||||
return -1;
|
||||
} else {
|
||||
ret = pdata->dev->fops->unlocked_ioctl (cmd, (unsigned long)(uintptr_t)kbuf, (void *)&(pdata->data));
|
||||
if (ret == 0) {
|
||||
if (copy_to_user((char *)(uintptr_t)arg, kbuf, _IOC_SIZE(cmd))) {
|
||||
vfree(kbuf);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (kbuf != NULL) {
|
||||
vfree(kbuf);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static long osal_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
long ret = 0;
|
||||
|
||||
GET_FILE(file);
|
||||
|
||||
ret = __osal_unlocked_ioctl(file, cmd, arg);
|
||||
PUT_FILE(file);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
static long __osal_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
int ret = -1;
|
||||
struct osal_private_data *pdata = file->private_data;
|
||||
char *kbuf = NULL;
|
||||
|
||||
if (DRVAL_DEBUG) {
|
||||
osal_printk("%s - file->private_data=%pK!\n", __FUNCTION__, pdata);
|
||||
}
|
||||
|
||||
if (((_IOC_SIZE(cmd) == 0) && (_IOC_DIR(cmd) != _IOC_NONE))) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((_IOC_DIR(cmd) != _IOC_NONE) && (((char *)(uintptr_t)arg) == NULL)) {
|
||||
osal_printk("%s - Input param err,it is null!\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (_IOC_DIR(cmd) == _IOC_NONE) {
|
||||
if (pdata->dev->fops->compat_ioctl == NULL) {
|
||||
return -1;
|
||||
} else {
|
||||
ret = pdata->dev->fops->compat_ioctl(cmd, arg, (void *)&(pdata->data));
|
||||
}
|
||||
} else if (_IOC_DIR(cmd) == _IOC_WRITE) {
|
||||
kbuf = (char *)vmalloc(_IOC_SIZE(cmd));
|
||||
if (kbuf == NULL) {
|
||||
osal_printk("%s - vmalloc failed!\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (copy_from_user(kbuf, (char *)(uintptr_t)arg, _IOC_SIZE(cmd))) {
|
||||
vfree(kbuf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pdata->dev->fops->compat_ioctl == NULL) {
|
||||
vfree(kbuf);
|
||||
return -1;
|
||||
} else {
|
||||
ret = pdata->dev->fops->compat_ioctl (cmd, (unsigned long)(uintptr_t)kbuf, (void *)&(pdata->data));
|
||||
}
|
||||
} else if (_IOC_DIR(cmd) == _IOC_READ) {
|
||||
kbuf = vmalloc(_IOC_SIZE(cmd));
|
||||
if (kbuf == NULL) {
|
||||
osal_printk("%s - vmalloc failed!\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
if (pdata->dev->fops->compat_ioctl == NULL) {
|
||||
vfree(kbuf);
|
||||
return -1;
|
||||
} else {
|
||||
ret = pdata->dev->fops->compat_ioctl (cmd, (unsigned long)(uintptr_t)kbuf, (void *)&(pdata->data));
|
||||
if (ret == 0) {
|
||||
if (copy_to_user((char *)(uintptr_t)arg, kbuf, _IOC_SIZE(cmd))) {
|
||||
vfree(kbuf);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (_IOC_DIR(cmd) == (_IOC_READ + _IOC_WRITE)) {
|
||||
kbuf = vmalloc(_IOC_SIZE(cmd));
|
||||
if (kbuf == NULL) {
|
||||
osal_printk("%s - vmalloc failed!\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (copy_from_user(kbuf, (char *)(uintptr_t)arg, _IOC_SIZE(cmd))) {
|
||||
vfree(kbuf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pdata->dev->fops->compat_ioctl == NULL) {
|
||||
vfree(kbuf);
|
||||
return -1;
|
||||
} else {
|
||||
ret = pdata->dev->fops->compat_ioctl (cmd, (unsigned long)(uintptr_t)kbuf, (void *)&(pdata->data));
|
||||
if (ret == 0) {
|
||||
if (copy_to_user((char *)(uintptr_t)arg, kbuf, _IOC_SIZE(cmd))) {
|
||||
vfree(kbuf);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (kbuf != NULL) {
|
||||
vfree(kbuf);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static long osal_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
long ret = 0;
|
||||
|
||||
GET_FILE(file);
|
||||
|
||||
ret = __osal_compat_ioctl(file, cmd, arg);
|
||||
PUT_FILE(file);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static unsigned int osal_poll(struct file *file, struct poll_table_struct *table)
|
||||
{
|
||||
struct osal_private_data *pdata = file->private_data;
|
||||
struct osal_poll t;
|
||||
unsigned int ret = 0;
|
||||
|
||||
GET_FILE(file);
|
||||
|
||||
if (DRVAL_DEBUG) {
|
||||
osal_printk("%s - table=%pK, file=%pK!\n", __FUNCTION__, table, file);
|
||||
}
|
||||
t.poll_table = table;
|
||||
t.data = file;
|
||||
if (pdata->dev->fops->poll != NULL) {
|
||||
ret = pdata->dev->fops->poll(&t, (void *)&(pdata->data));
|
||||
}
|
||||
|
||||
PUT_FILE(file);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __osal_valid_mmap_phys_addr_range(unsigned long pfn, size_t size)
|
||||
{
|
||||
/* check physical addr greater than the max addr supported by the system */
|
||||
if ((pfn + (size >> PAGE_SHIFT)) > (1 + ((~0UL) >> PAGE_SHIFT))) {
|
||||
osal_printk("--%s - %d--!\n", __FUNCTION__, __LINE__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* CMA need to alloc ram region, so annotate the code as follows */
|
||||
#if 0
|
||||
/* check physical addr is ram region */
|
||||
if (pfn_valid(pfn) || pfn_valid(pfn + (size >> PAGE_SHIFT))) {
|
||||
osal_printk("--%s - %d--!\n", __FUNCTION__, __LINE__);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* It's necessary for the variable "size" to align 4k(page_size). */
|
||||
#define PAGE_SIZE_MASK 0xfffffffffffff000ULL
|
||||
if ((unsigned long)size & (~PAGE_SIZE_MASK)) {
|
||||
osal_printk("--%s - %d--!\n", __FUNCTION__, __LINE__);
|
||||
return 0;
|
||||
}
|
||||
#undef PAGE_SIZE_MASK
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int osal_mmap(struct file *file, struct vm_area_struct *vm)
|
||||
{
|
||||
struct osal_vm osal_vm;
|
||||
struct osal_private_data *pdata = file->private_data;
|
||||
osal_vm.vm = vm;
|
||||
|
||||
if (!__osal_valid_mmap_phys_addr_range(vm->vm_pgoff, vm->vm_end - vm->vm_start)) {
|
||||
osal_printk("\n%s - invalid argument size=%ld!!!\n", __FUNCTION__, vm->vm_end - vm->vm_start);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (DRVAL_DEBUG) {
|
||||
osal_printk("%s - start=%lx, end=%lx!, off=%lx\n", __FUNCTION__, vm->vm_start, vm->vm_end, vm->vm_pgoff);
|
||||
}
|
||||
if (pdata->dev->fops->mmap != NULL) {
|
||||
return pdata->dev->fops->mmap(&osal_vm, vm->vm_start, vm->vm_end, vm->vm_pgoff, (void *)&(pdata->data));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct file_operations s_osal_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = osal_open,
|
||||
.read = osal_read,
|
||||
.write = osal_write,
|
||||
.llseek = osal_llseek,
|
||||
.unlocked_ioctl = osal_unlocked_ioctl,
|
||||
.release = osal_release,
|
||||
.poll = osal_poll,
|
||||
.mmap = osal_mmap,
|
||||
#ifdef CONFIG_COMPAT
|
||||
.compat_ioctl = osal_compat_ioctl,
|
||||
#endif
|
||||
};
|
||||
|
||||
static int osal_pm_prepare(struct media_device *media)
|
||||
{
|
||||
osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev);
|
||||
if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_prepare) {
|
||||
return coat_dev->osal_dev.osal_pmops->pm_prepare(&(coat_dev->osal_dev));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void osal_pm_complete(struct media_device *media)
|
||||
{
|
||||
osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev);
|
||||
if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_complete) {
|
||||
coat_dev->osal_dev.osal_pmops->pm_complete(&(coat_dev->osal_dev));
|
||||
}
|
||||
}
|
||||
|
||||
static int osal_pm_suspend(struct media_device *media)
|
||||
{
|
||||
osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev);
|
||||
if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_suspend) {
|
||||
return coat_dev->osal_dev.osal_pmops->pm_suspend(&(coat_dev->osal_dev));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int osal_pm_resume(struct media_device *media)
|
||||
{
|
||||
osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev);
|
||||
if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_resume) {
|
||||
return coat_dev->osal_dev.osal_pmops->pm_resume(&(coat_dev->osal_dev));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int osal_pm_freeze(struct media_device *media)
|
||||
{
|
||||
osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev);
|
||||
if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_freeze) {
|
||||
return coat_dev->osal_dev.osal_pmops->pm_freeze(&(coat_dev->osal_dev));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int osal_pm_thaw(struct media_device *media)
|
||||
{
|
||||
osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev);
|
||||
if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_thaw) {
|
||||
return coat_dev->osal_dev.osal_pmops->pm_thaw(&(coat_dev->osal_dev));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int osal_pm_poweroff(struct media_device *media)
|
||||
{
|
||||
osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev);
|
||||
if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_poweroff) {
|
||||
return coat_dev->osal_dev.osal_pmops->pm_poweroff(&(coat_dev->osal_dev));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int osal_pm_restore(struct media_device *media)
|
||||
{
|
||||
osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev);
|
||||
if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_restore) {
|
||||
return coat_dev->osal_dev.osal_pmops->pm_restore(&(coat_dev->osal_dev));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int osal_pm_suspend_late(struct media_device *media)
|
||||
{
|
||||
osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev);
|
||||
if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_suspend_late) {
|
||||
return coat_dev->osal_dev.osal_pmops->pm_suspend_late(&(coat_dev->osal_dev));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int osal_pm_resume_early(struct media_device *media)
|
||||
{
|
||||
osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev);
|
||||
if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_resume_early) {
|
||||
return coat_dev->osal_dev.osal_pmops->pm_resume_early(&(coat_dev->osal_dev));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int osal_pm_freeze_late(struct media_device *media)
|
||||
{
|
||||
osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev);
|
||||
if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_freeze_late) {
|
||||
return coat_dev->osal_dev.osal_pmops->pm_freeze_late(&(coat_dev->osal_dev));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int osal_pm_thaw_early(struct media_device *media)
|
||||
{
|
||||
osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev);
|
||||
if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_thaw_early) {
|
||||
return coat_dev->osal_dev.osal_pmops->pm_thaw_early(&(coat_dev->osal_dev));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int osal_pm_poweroff_late(struct media_device *media)
|
||||
{
|
||||
osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev);
|
||||
if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_poweroff_late) {
|
||||
return coat_dev->osal_dev.osal_pmops->pm_poweroff_late(&(coat_dev->osal_dev));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int osal_pm_restore_early(struct media_device *media)
|
||||
{
|
||||
osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev);
|
||||
if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_restore_early) {
|
||||
return coat_dev->osal_dev.osal_pmops->pm_restore_early(&(coat_dev->osal_dev));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int osal_pm_suspend_noirq(struct media_device *media)
|
||||
{
|
||||
osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev);
|
||||
if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_suspend_noirq) {
|
||||
return coat_dev->osal_dev.osal_pmops->pm_suspend_noirq(&(coat_dev->osal_dev));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int osal_pm_resume_noirq(struct media_device *media)
|
||||
{
|
||||
osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev);
|
||||
if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_resume_noirq) {
|
||||
return coat_dev->osal_dev.osal_pmops->pm_resume_noirq(&(coat_dev->osal_dev));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int osal_pm_freeze_noirq(struct media_device *media)
|
||||
{
|
||||
osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev);
|
||||
if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_freeze_noirq) {
|
||||
return coat_dev->osal_dev.osal_pmops->pm_freeze_noirq(&(coat_dev->osal_dev));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int osal_pm_thaw_noirq(struct media_device *media)
|
||||
{
|
||||
osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev);
|
||||
if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_thaw_noirq) {
|
||||
return coat_dev->osal_dev.osal_pmops->pm_thaw_noirq(&(coat_dev->osal_dev));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int osal_pm_poweroff_noirq(struct media_device *media)
|
||||
{
|
||||
osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev);
|
||||
if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_poweroff_noirq) {
|
||||
return coat_dev->osal_dev.osal_pmops->pm_poweroff_noirq(&(coat_dev->osal_dev));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int osal_pm_restore_noirq(struct media_device *media)
|
||||
{
|
||||
osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev);
|
||||
if (coat_dev->osal_dev.osal_pmops && coat_dev->osal_dev.osal_pmops->pm_restore_noirq) {
|
||||
return coat_dev->osal_dev.osal_pmops->pm_restore_noirq(&(coat_dev->osal_dev));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int osal_devfreq_target(struct media_device *media, unsigned long *freq, unsigned int flags)
|
||||
{
|
||||
osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev);
|
||||
if (coat_dev->osal_dev.osal_profile->target) {
|
||||
return coat_dev->osal_dev.osal_profile->target(&(coat_dev->osal_dev), freq, flags);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int osal_devfreq_get_dev_status(struct media_device *media, struct osal_devfreq_dev_status *stat)
|
||||
{
|
||||
osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev);
|
||||
if (coat_dev->osal_dev.osal_profile->get_dev_status) {
|
||||
return coat_dev->osal_dev.osal_profile->get_dev_status(&(coat_dev->osal_dev), stat);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int osal_devfreq_get_cur_freq(struct media_device *media, unsigned long *freq)
|
||||
{
|
||||
osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev);
|
||||
if (coat_dev->osal_dev.osal_profile->get_cur_freq) {
|
||||
return coat_dev->osal_dev.osal_profile->get_cur_freq(&(coat_dev->osal_dev), freq);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void osal_devfreq_exit(struct media_device *media)
|
||||
{
|
||||
osal_coat_dev_t *coat_dev = container_of(media, struct osal_coat_dev, media_dev);
|
||||
|
||||
if (coat_dev->osal_dev.osal_profile->exit) {
|
||||
return coat_dev->osal_dev.osal_profile->exit(&(coat_dev->osal_dev));
|
||||
}
|
||||
}
|
||||
|
||||
int osal_devfreq_register(osal_dev_t *osal_dev, struct osal_devfreq_dev_profile *osal_profile,
|
||||
const char *governor, void *data)
|
||||
{
|
||||
struct media_device *media = NULL;
|
||||
osal_devfreq_para_t devfreq_para = { 0 };
|
||||
|
||||
if ((osal_dev == NULL) || (osal_profile == NULL)) {
|
||||
osal_printk("%s - parameter invalid!\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
media = &(((osal_coat_dev_t *)(osal_dev->dev))->media_dev);
|
||||
if ((governor != NULL) && (osal_strcmp(governor, "userspace") == 0)) {
|
||||
osal_printk("Not supported governor\r\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
osal_dev->osal_profile = osal_profile;
|
||||
|
||||
devfreq_para.initial_freq = osal_dev->osal_profile->initial_freq;
|
||||
devfreq_para.polling_ms = osal_dev->osal_profile->polling_ms;
|
||||
devfreq_para.freq_table = osal_dev->osal_profile->freq_table;
|
||||
devfreq_para.max_state = osal_dev->osal_profile->max_state;
|
||||
|
||||
return media_devfreq_register(media, &devfreq_para);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_devfreq_register);
|
||||
|
||||
void osal_devfreq_unregister(osal_dev_t *osal_dev)
|
||||
{
|
||||
struct media_device *media = NULL;
|
||||
|
||||
if ((osal_dev == NULL) || (osal_dev->osal_profile == NULL)) {
|
||||
osal_printk("%s - parameter invalid!\n", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
media = &(((osal_coat_dev_t *)(osal_dev->dev))->media_dev);
|
||||
media_devfreq_unregister(media);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_devfreq_unregister);
|
||||
|
||||
static struct media_ops s_osal_pmops = {
|
||||
.pm_prepare = osal_pm_prepare,
|
||||
.pm_complete = osal_pm_complete,
|
||||
.pm_suspend = osal_pm_suspend,
|
||||
.pm_resume = osal_pm_resume,
|
||||
.pm_freeze = osal_pm_freeze,
|
||||
.pm_thaw = osal_pm_thaw,
|
||||
.pm_poweroff = osal_pm_poweroff,
|
||||
.pm_restore = osal_pm_restore,
|
||||
.pm_suspend_late = osal_pm_suspend_late,
|
||||
.pm_resume_early = osal_pm_resume_early,
|
||||
.pm_freeze_late = osal_pm_freeze_late,
|
||||
.pm_thaw_early = osal_pm_thaw_early,
|
||||
.pm_poweroff_late = osal_pm_poweroff_late,
|
||||
.pm_restore_early = osal_pm_restore_early,
|
||||
.pm_suspend_noirq = osal_pm_suspend_noirq,
|
||||
.pm_resume_noirq = osal_pm_resume_noirq,
|
||||
.pm_freeze_noirq = osal_pm_freeze_noirq,
|
||||
.pm_thaw_noirq = osal_pm_thaw_noirq,
|
||||
.pm_poweroff_noirq = osal_pm_poweroff_noirq,
|
||||
.pm_restore_noirq = osal_pm_restore_noirq,
|
||||
|
||||
.devfreq_target = osal_devfreq_target,
|
||||
.devfreq_get_dev_status = osal_devfreq_get_dev_status,
|
||||
.devfreq_get_cur_freq = osal_devfreq_get_cur_freq,
|
||||
.devfreq_exit = osal_devfreq_exit,
|
||||
};
|
||||
|
||||
osal_dev_t *osal_createdev(const char *name)
|
||||
{
|
||||
osal_coat_dev_t *pdev = NULL;
|
||||
if (name == NULL) {
|
||||
osal_printk("%s - parameter invalid!\n", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
pdev = (osal_coat_dev_t *)kmalloc(sizeof(osal_coat_dev_t), GFP_KERNEL);
|
||||
if (pdev == NULL) {
|
||||
osal_printk("%s - kmalloc error!\n", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
memset(pdev, 0, sizeof(osal_coat_dev_t));
|
||||
osal_strncpy(pdev->osal_dev.name, name, sizeof(pdev->osal_dev.name) - 1);
|
||||
pdev->osal_dev.dev = pdev;
|
||||
return &(pdev->osal_dev);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_createdev);
|
||||
|
||||
int osal_destroydev(osal_dev_t *osal_dev)
|
||||
{
|
||||
osal_coat_dev_t *pdev = NULL;
|
||||
if (osal_dev == NULL) {
|
||||
osal_printk("%s - parameter invalid!\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
pdev = osal_dev->dev;
|
||||
if (pdev == NULL) {
|
||||
osal_printk("%s - parameter invalid!\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
kfree(pdev);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(osal_destroydev);
|
||||
|
||||
int osal_registerdevice(osal_dev_t *osal_dev)
|
||||
{
|
||||
struct media_device *media = NULL;
|
||||
if ((osal_dev == NULL) || (osal_dev->fops == NULL)) {
|
||||
osal_printk("%s - parameter invalid!\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
media = &(((osal_coat_dev_t *)(osal_dev->dev))->media_dev);
|
||||
if (osal_dev->minor != 0) {
|
||||
media->minor = osal_dev->minor;
|
||||
} else {
|
||||
media->minor = MEDIA_DYNAMIC_MINOR;
|
||||
}
|
||||
media->owner = THIS_MODULE;
|
||||
media->fops = &s_osal_fops;
|
||||
media->drvops = &s_osal_pmops;
|
||||
osal_strncpy(media->devfs_name, osal_dev->name, sizeof(media->devfs_name) - 1);
|
||||
return media_register(media);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_registerdevice);
|
||||
|
||||
void osal_deregisterdevice(osal_dev_t *pdev)
|
||||
{
|
||||
if (pdev == NULL) {
|
||||
osal_printk("%s - parameter invalid!\n", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
media_unregister((struct media_device *)&(((osal_coat_dev_t *)(pdev->dev))->media_dev));
|
||||
}
|
||||
EXPORT_SYMBOL(osal_deregisterdevice);
|
||||
|
||||
void osal_poll_wait(osal_poll_t *table, osal_wait_t *wait)
|
||||
{
|
||||
if (DRVAL_DEBUG) {
|
||||
osal_printk("%s - call poll_wait +!, table=%pK, file=%pK\n", __FUNCTION__, table->poll_table, table->data);
|
||||
}
|
||||
|
||||
poll_wait ((struct file *)table->data, (wait_queue_head_t *)(wait->wait), table->poll_table);
|
||||
|
||||
if (DRVAL_DEBUG) {
|
||||
osal_printk("%s - call poll_wait -!\n", __FUNCTION__);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(osal_poll_wait);
|
||||
|
||||
#if 0
|
||||
void osal_pgprot_noncached(osal_vm_t *vm) {
|
||||
struct vm_area_struct *v = (struct vm_area_struct *)(vm->vm);
|
||||
v->vm_page_prot = pgprot_noncached(v->vm_page_prot);
|
||||
}
|
||||
#else
|
||||
void osal_pgprot_noncached(osal_vm_t *vm)
|
||||
{
|
||||
struct vm_area_struct *v = (struct vm_area_struct *)(vm->vm);
|
||||
v->vm_page_prot = pgprot_writecombine(v->vm_page_prot);
|
||||
}
|
||||
|
||||
#endif
|
||||
EXPORT_SYMBOL(osal_pgprot_noncached);
|
||||
|
||||
void osal_pgprot_cached(osal_vm_t *vm)
|
||||
{
|
||||
struct vm_area_struct *v = (struct vm_area_struct *)(vm->vm);
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
v->vm_page_prot = __pgprot(pgprot_val(v->vm_page_prot)
|
||||
| PTE_VALID | PTE_DIRTY | PTE_AF);
|
||||
#else
|
||||
|
||||
v->vm_page_prot = __pgprot(pgprot_val(v->vm_page_prot) | L_PTE_PRESENT
|
||||
| L_PTE_YOUNG | L_PTE_DIRTY | L_PTE_MT_DEV_CACHED);
|
||||
#endif
|
||||
}
|
||||
EXPORT_SYMBOL(osal_pgprot_cached);
|
||||
|
||||
void osal_pgprot_writecombine(osal_vm_t *vm)
|
||||
{
|
||||
struct vm_area_struct *v = (struct vm_area_struct *)(vm->vm);
|
||||
v->vm_page_prot = pgprot_writecombine(v->vm_page_prot);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_pgprot_writecombine);
|
||||
|
||||
void osal_pgprot_stronglyordered(osal_vm_t *vm)
|
||||
{
|
||||
struct vm_area_struct *v = (struct vm_area_struct *)(vm->vm);
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
v->vm_page_prot = pgprot_device(v->vm_page_prot);
|
||||
#else
|
||||
v->vm_page_prot = pgprot_stronglyordered(v->vm_page_prot);
|
||||
#endif
|
||||
}
|
||||
EXPORT_SYMBOL(osal_pgprot_stronglyordered);
|
||||
|
||||
int osal_remap_pfn_range(osal_vm_t *vm, unsigned long addr, unsigned long pfn, unsigned long size)
|
||||
{
|
||||
struct vm_area_struct *v = (struct vm_area_struct *)(vm->vm);
|
||||
if (size == 0) {
|
||||
return -EPERM;
|
||||
}
|
||||
return remap_pfn_range(v, addr, pfn, size, v->vm_page_prot);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_remap_pfn_range);
|
||||
|
||||
int osal_io_remap_pfn_range(osal_vm_t *vm, unsigned long addr, unsigned long pfn, unsigned long size)
|
||||
{
|
||||
struct vm_area_struct *v = (struct vm_area_struct *)(vm->vm);
|
||||
v->vm_flags |= VM_IO;
|
||||
if (size == 0) {
|
||||
return -EPERM;
|
||||
}
|
||||
return io_remap_pfn_range(v, addr, pfn, size, v->vm_page_prot);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_io_remap_pfn_range);
|
||||
|
||||
#ifdef CONFIG_SNAPSHOT_BOOT
|
||||
int osal_call_usermodehelper_force(char *path, char **argv, char **envp, int wait)
|
||||
{
|
||||
return call_usermodehelper_force(path, argv, envp, wait);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_call_usermodehelper_force);
|
||||
#endif
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (c) XMEDIA. All rights reserved.
|
||||
*/
|
||||
#include "osal.h"
|
||||
#include <linux/version.h>
|
||||
#include <linux/fs.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
struct file *klib_fopen(const char *filename, int flags, int mode)
|
||||
{
|
||||
struct file *filp = filp_open(filename, flags, mode);
|
||||
return (IS_ERR(filp)) ? NULL : filp;
|
||||
}
|
||||
|
||||
void klib_fclose(struct file *filp)
|
||||
{
|
||||
if (filp != NULL) {
|
||||
filp_close(filp, NULL);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
int klib_fwrite(const char *buf, int len, struct file *filp)
|
||||
{
|
||||
int writelen;
|
||||
|
||||
if (filp == NULL) {
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
writelen = __kernel_write(filp, buf, len, &filp->f_pos);
|
||||
return writelen;
|
||||
}
|
||||
|
||||
int klib_fread(char *buf, unsigned int len, struct file *filp)
|
||||
{
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0)
|
||||
mm_segment_t old_fs;
|
||||
int readlen;
|
||||
#endif
|
||||
if (filp == NULL) {
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0)
|
||||
old_fs = get_fs();
|
||||
set_fs(get_ds());
|
||||
/* The cast to a user pointer is valid due to the set_fs() */
|
||||
readlen = vfs_read(filp, (void __user *)buf, len, &filp->f_pos);
|
||||
set_fs(old_fs);
|
||||
return readlen;
|
||||
#else
|
||||
return kernel_read(filp, (void __user*)buf, len, &filp->f_pos);
|
||||
#endif
|
||||
}
|
||||
|
||||
void *osal_klib_fopen(const char *filename, int flags, int mode)
|
||||
{
|
||||
return (void *)klib_fopen(filename, flags, mode);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_klib_fopen);
|
||||
|
||||
void osal_klib_fclose(void *filp)
|
||||
{
|
||||
klib_fclose((struct file *)filp);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_klib_fclose);
|
||||
|
||||
int osal_klib_fwrite(const char *buf, int len, void *filp)
|
||||
{
|
||||
return klib_fwrite(buf, len, (struct file *)filp);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_klib_fwrite);
|
||||
|
||||
int osal_klib_fread(char *buf, unsigned int len, void *filp)
|
||||
{
|
||||
return klib_fread(buf, len, (struct file *)filp);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_klib_fread);
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) XMEDIA. All rights reserved.
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include "osal.h"
|
||||
|
||||
extern void osal_proc_init(void);
|
||||
extern void osal_proc_exit(void);
|
||||
extern int media_init(void);
|
||||
extern void media_exit(void);
|
||||
extern int media_mem_init(void);
|
||||
extern void media_mem_exit(void);
|
||||
extern void osal_device_init(void);
|
||||
|
||||
static int __init osal_init(void)
|
||||
{
|
||||
osal_device_init();
|
||||
osal_proc_init();
|
||||
media_init();
|
||||
media_mem_init();
|
||||
osal_printk("osal %s init success!\n", OSAL_VERSION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit osal_exit(void)
|
||||
{
|
||||
media_exit();
|
||||
media_mem_exit();
|
||||
osal_proc_exit();
|
||||
osal_printk("osal v1.0 exit!\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef MODULE
|
||||
|
||||
module_init(osal_init);
|
||||
module_exit(osal_exit);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
#else
|
||||
|
||||
int __init osal_driver_init(void)
|
||||
{
|
||||
return osal_init();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (c) XMEDIA. All rights reserved.
|
||||
*/
|
||||
#include "osal.h"
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/printk.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
int osal_request_irq(unsigned int irq, osal_irq_handler_t handler, osal_irq_handler_t thread_fn, const char *name,
|
||||
void *dev)
|
||||
{
|
||||
unsigned long flags = IRQF_SHARED;
|
||||
|
||||
return request_threaded_irq(irq, (irq_handler_t)handler, (irq_handler_t)thread_fn, flags, name, dev);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_request_irq);
|
||||
void osal_free_irq(unsigned int irq, void *dev)
|
||||
{
|
||||
free_irq(irq, dev);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_free_irq);
|
||||
|
||||
int osal_in_interrupt(void)
|
||||
{
|
||||
return in_interrupt();
|
||||
}
|
||||
EXPORT_SYMBOL(osal_in_interrupt);
|
||||
|
||||
#if 0
|
||||
#ifdef CONFIG_ARM_GIC
|
||||
|
||||
#define DIS_IRQ_CNT 2
|
||||
struct gic_sgi_handle {
|
||||
unsigned int irq;
|
||||
void (*handle)(unsigned int cpu_intrf,
|
||||
unsigned int irq_num,
|
||||
struct pt_regs *regs);
|
||||
};
|
||||
int osal_register_gic_handle(unsigned int index, unsigned int irq,
|
||||
osal_gic_handle_t handle, const char *name, void *dev)
|
||||
{
|
||||
extern struct gic_sgi_handle dis_irq_handle[DIS_IRQ_CNT];
|
||||
|
||||
|
||||
if (index >= DIS_IRQ_CNT) {
|
||||
printk("index(%d) is error.\n", index);
|
||||
return -1;
|
||||
}
|
||||
dis_irq_handle[index].irq = irq;
|
||||
dis_irq_handle[index].handle = (void (*)(unsigned int, unsigned int, struct pt_regs *))(handle);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(osal_register_gic_handle);
|
||||
|
||||
int osal_unregister_gic_handle(unsigned int index, unsigned int irq, void *dev)
|
||||
{
|
||||
extern struct gic_sgi_handle dis_irq_handle[DIS_IRQ_CNT];
|
||||
|
||||
if (index >= DIS_IRQ_CNT) {
|
||||
printk("index(%d) is error.\n", index);
|
||||
return -1;
|
||||
}
|
||||
dis_irq_handle[index].irq = 0xF;
|
||||
dis_irq_handle[index].handle = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(osal_unregister_gic_handle);
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright (c) XMEDIA. All rights reserved.
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
// #include <asm/div64.h>
|
||||
#include <linux/random.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <asm/neon.h>
|
||||
#include "osal.h"
|
||||
|
||||
int osal_isdigit(int c)
|
||||
{
|
||||
return isdigit(c);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_isdigit);
|
||||
|
||||
#ifdef CONFIG_KERNEL_MODE_NEON
|
||||
void osal_kernel_neon_begin(void)
|
||||
{
|
||||
kernel_neon_begin();
|
||||
}
|
||||
EXPORT_SYMBOL(osal_kernel_neon_begin);
|
||||
|
||||
void osal_kernel_neon_end(void)
|
||||
{
|
||||
kernel_neon_end();
|
||||
}
|
||||
EXPORT_SYMBOL(osal_kernel_neon_end);
|
||||
#endif
|
||||
|
||||
/* the result of u64/u32. */
|
||||
unsigned long long osal_div_u64(unsigned long long dividend, unsigned int divisor)
|
||||
{
|
||||
return div_u64(dividend, divisor);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_div_u64);
|
||||
|
||||
/* the result of s64/s32. */
|
||||
long long osal_div_s64(long long dividend, int divisor)
|
||||
{
|
||||
return div_s64(dividend, divisor);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_div_s64);
|
||||
|
||||
/* the result of u64/u64. */
|
||||
unsigned long long osal_div64_u64(unsigned long long dividend, unsigned long long divisor)
|
||||
{
|
||||
return div64_u64(dividend, divisor);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_div64_u64);
|
||||
|
||||
/* the result of s64/s64. */
|
||||
long long osal_div64_s64(long long dividend, long long divisor)
|
||||
{
|
||||
return div64_s64(dividend, divisor);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_div64_s64);
|
||||
|
||||
/* the remainder of u64/u32. */
|
||||
unsigned long long osal_div_u64_rem(unsigned long long dividend, unsigned int divisor)
|
||||
{
|
||||
unsigned int remainder;
|
||||
|
||||
div_u64_rem(dividend, divisor, &remainder);
|
||||
|
||||
return remainder;
|
||||
}
|
||||
EXPORT_SYMBOL(osal_div_u64_rem);
|
||||
|
||||
/* the remainder of s64/s32. */
|
||||
long long osal_div_s64_rem(long long dividend, int divisor)
|
||||
{
|
||||
int remainder;
|
||||
|
||||
div_s64_rem(dividend, divisor, &remainder);
|
||||
|
||||
return remainder;
|
||||
}
|
||||
EXPORT_SYMBOL(osal_div_s64_rem);
|
||||
|
||||
/* the remainder of u64/u64. */
|
||||
unsigned long long osal_div64_u64_rem(unsigned long long dividend, unsigned long long divisor)
|
||||
{
|
||||
unsigned long long remainder;
|
||||
|
||||
div64_u64_rem(dividend, divisor, &remainder);
|
||||
|
||||
return remainder;
|
||||
}
|
||||
EXPORT_SYMBOL(osal_div64_u64_rem);
|
||||
|
||||
unsigned int osal_random(void)
|
||||
{
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0)
|
||||
return random32();
|
||||
#else
|
||||
return get_random_int();
|
||||
#endif
|
||||
}
|
||||
EXPORT_SYMBOL(osal_random);
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (c) XMEDIA. All rights reserved.
|
||||
*/
|
||||
#include "osal.h"
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/printk.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
int osal_mutex_init(osal_mutex_t *mutex)
|
||||
{
|
||||
struct mutex *p = NULL;
|
||||
if (mutex == NULL) {
|
||||
osal_printk("%s - parameter invalid!\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
p = kmalloc(sizeof(struct mutex), GFP_KERNEL);
|
||||
if (p == NULL) {
|
||||
osal_printk("%s - kmalloc error!\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
mutex_init(p);
|
||||
mutex->mutex = p;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(osal_mutex_init);
|
||||
|
||||
int osal_mutex_lock(osal_mutex_t *mutex)
|
||||
{
|
||||
struct mutex *p = NULL;
|
||||
if (mutex == NULL) {
|
||||
osal_printk("%s - parameter invalid!\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
p = (struct mutex *)(mutex->mutex);
|
||||
mutex_lock(p);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(osal_mutex_lock);
|
||||
|
||||
int osal_mutex_lock_interruptible(osal_mutex_t *mutex)
|
||||
{
|
||||
struct mutex *p = NULL;
|
||||
if (mutex == NULL) {
|
||||
osal_printk("%s - parameter invalid!\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
p = (struct mutex *)(mutex->mutex);
|
||||
return mutex_lock_interruptible(p);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_mutex_lock_interruptible);
|
||||
|
||||
int osal_mutex_trylock(osal_mutex_t *mutex)
|
||||
{
|
||||
struct mutex *p = NULL;
|
||||
if (mutex == NULL) {
|
||||
osal_printk("%s - parameter invalid!\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
p = (struct mutex *)(mutex->mutex);
|
||||
|
||||
return mutex_trylock(p);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_mutex_trylock);
|
||||
|
||||
void osal_mutex_unlock(osal_mutex_t *mutex)
|
||||
{
|
||||
struct mutex *p = NULL;
|
||||
p = (struct mutex *)(mutex->mutex);
|
||||
|
||||
mutex_unlock(p);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_mutex_unlock);
|
||||
|
||||
void osal_mutex_destroy(osal_mutex_t *mutex)
|
||||
{
|
||||
if((mutex != NULL) && (mutex->mutex != NULL)) {
|
||||
kfree((struct mutex *)(mutex->mutex));
|
||||
mutex->mutex = NULL;
|
||||
} else {
|
||||
osal_printk("%s - parameter invalid!\n", __FUNCTION__);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(osal_mutex_destroy);
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (c) XMEDIA. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/module.h>
|
||||
#include "osal.h"
|
||||
|
||||
OSAL_LIST_HEAD(nb_list);
|
||||
|
||||
struct nb_node {
|
||||
struct osal_notifier_block *osal_nb;
|
||||
struct notifier_block *nb;
|
||||
struct osal_list_head node;
|
||||
};
|
||||
|
||||
static struct osal_notifier_block *osal_find_ob(struct notifier_block *nb)
|
||||
{
|
||||
struct osal_list_head *this = NULL;
|
||||
if (osal_list_empty(&nb_list)) {
|
||||
osal_printk("find nb failed! nb_list is empty!\n");
|
||||
return NULL;
|
||||
}
|
||||
osal_list_for_each(this, &nb_list) {
|
||||
struct nb_node *ns = osal_list_entry(this, struct nb_node, node);
|
||||
if (ns->nb == nb) {
|
||||
return ns->osal_nb;
|
||||
}
|
||||
}
|
||||
osal_printk("find ob failed!\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int osal_del_nb(struct osal_notifier_block *nb)
|
||||
{
|
||||
struct osal_list_head *this = NULL;
|
||||
struct osal_list_head *next = NULL;
|
||||
if (osal_list_empty(&nb_list)) {
|
||||
osal_printk("find nb failed! nb_list is empty!\n");
|
||||
return -1;
|
||||
}
|
||||
osal_list_for_each_safe(this, next, &nb_list) {
|
||||
struct nb_node *ns = osal_list_entry(this, struct nb_node, node);
|
||||
if (ns->osal_nb == nb) {
|
||||
osal_list_del(this);
|
||||
kfree(ns);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
osal_printk("del nb failed!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int osal_notifier(struct notifier_block *nb, unsigned long action, void *data)
|
||||
{
|
||||
struct osal_notifier_block *ob = osal_find_ob(nb);
|
||||
if ((ob != NULL) && (ob->notifier_call != NULL)) {
|
||||
return ob->notifier_call(ob, action, data);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int osal_register_reboot_notifier(struct osal_notifier_block *ob)
|
||||
{
|
||||
struct notifier_block *nb = NULL;
|
||||
struct nb_node *node = NULL;
|
||||
|
||||
nb = kmalloc(sizeof(struct notifier_block), GFP_KERNEL);
|
||||
if (nb == NULL) {
|
||||
osal_printk("osal_register_reboot_notifier malloc nb failed!\n");
|
||||
return -1;
|
||||
}
|
||||
memset(nb, 0, sizeof(struct notifier_block));
|
||||
|
||||
node = kmalloc(sizeof(struct nb_node), GFP_KERNEL);
|
||||
if (node == NULL) {
|
||||
osal_printk("osal_register_reboot_notifier kmalloc nb_node failed!\n");
|
||||
kfree(nb);
|
||||
return -1;
|
||||
}
|
||||
memset(node, 0, sizeof(struct nb_node));
|
||||
|
||||
nb->notifier_call = osal_notifier;
|
||||
register_reboot_notifier(nb);
|
||||
ob->notifier_block = nb;
|
||||
node->osal_nb = ob;
|
||||
node->nb = nb;
|
||||
osal_list_add(&(node->node), &nb_list);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(osal_register_reboot_notifier);
|
||||
|
||||
int osal_unregister_reboot_notifier(struct osal_notifier_block *nb)
|
||||
{
|
||||
if (nb != NULL) {
|
||||
osal_del_nb(nb);
|
||||
unregister_reboot_notifier((struct notifier_block *)nb->notifier_block);
|
||||
kfree((struct notifier_block *)nb->notifier_block);
|
||||
nb->notifier_block = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(osal_unregister_reboot_notifier);
|
||||
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (c) XMEDIA. All rights reserved.
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#if 0
|
||||
int osal_platform_driver_register(struct platform_driver *drv)
|
||||
{
|
||||
return __platform_driver_register(drv, THIS_MODULE);
|
||||
}
|
||||
void osal_platform_driver_unregister(struct platform_driver *drv)
|
||||
{
|
||||
return platform_driver_unregister(drv);
|
||||
}
|
||||
struct resource *osal_platform_get_resource_byname(struct platform_device *dev, unsigned int type, const char *name)
|
||||
{
|
||||
return platform_get_resource_byname(dev, type, name);
|
||||
}
|
||||
|
||||
#else
|
||||
int osal_platform_driver_register(void *drv)
|
||||
{
|
||||
return __platform_driver_register((struct platform_driver *)drv, THIS_MODULE);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_platform_driver_register);
|
||||
|
||||
void osal_platform_driver_unregister(void *drv)
|
||||
{
|
||||
return platform_driver_unregister((struct platform_driver *)drv);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_platform_driver_unregister);
|
||||
|
||||
void *osal_platform_get_resource_byname(void *dev, unsigned int type,
|
||||
const char *name)
|
||||
{
|
||||
return (void *)platform_get_resource_byname((struct platform_device *)dev, type, name);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_platform_get_resource_byname);
|
||||
|
||||
void *osal_platform_get_resource(void *dev, unsigned int type, unsigned int num)
|
||||
{
|
||||
return (void *)platform_get_resource((struct platform_device *)dev, type, num);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_platform_get_resource);
|
||||
|
||||
int osal_platform_get_irq(void *dev, unsigned int num)
|
||||
{
|
||||
return platform_get_irq((struct platform_device *)dev, num);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_platform_get_irq);
|
||||
|
||||
int osal_platform_get_irq_byname(void *dev, const char *name)
|
||||
{
|
||||
return platform_get_irq_byname((struct platform_device *)dev, name);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_platform_get_irq_byname);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,311 @@
|
||||
/*
|
||||
* Copyright (c) XMEDIA. All rights reserved.
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/printk.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/slab.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/version.h>
|
||||
|
||||
#include "osal.h"
|
||||
|
||||
#define OSAL_PROC_DEBUG 0
|
||||
|
||||
static struct osal_list_head list;
|
||||
static osal_proc_entry_t *proc_entry = NULL;
|
||||
|
||||
static int osal_seq_show(struct seq_file *s, void *p)
|
||||
{
|
||||
osal_proc_entry_t *oldsentry = s->private;
|
||||
osal_proc_entry_t sentry;
|
||||
if (oldsentry == NULL) {
|
||||
osal_printk("%s - parameter invalid!\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
memset(&sentry, 0, sizeof(osal_proc_entry_t));
|
||||
osal_memcpy(sentry.name, oldsentry->name, sizeof(sentry.name));
|
||||
/* only these two parameters are used */
|
||||
sentry.seqfile = s;
|
||||
sentry.private = oldsentry->private;
|
||||
oldsentry->read(&sentry);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0)
|
||||
static ssize_t osal_procwrite(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
|
||||
{
|
||||
osal_proc_entry_t *sentry = ((struct seq_file *)(file->private_data))->private;
|
||||
return sentry->write(sentry, (char *)buf, count, (long long *)ppos);
|
||||
}
|
||||
#else
|
||||
static ssize_t osal_procwrite(struct file *file, const char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
osal_proc_entry_t *item = PDE_DATA(file_inode(file));
|
||||
|
||||
if ((item != NULL) && (item->write != NULL)) {
|
||||
return item->write(item, buf, count, (long long *)ppos);
|
||||
}
|
||||
|
||||
return -ENOSYS;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int osal_procopen(struct inode *inode, struct file *file)
|
||||
{
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0)
|
||||
osal_proc_entry_t *sentry = PDE(inode)->data;
|
||||
#else
|
||||
osal_proc_entry_t *sentry = PDE_DATA(inode);
|
||||
#endif
|
||||
if ((sentry != NULL) && (sentry->open != NULL)) {
|
||||
sentry->open(sentry);
|
||||
}
|
||||
return single_open(file, osal_seq_show, sentry);
|
||||
}
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0)
|
||||
static struct file_operations osal_proc_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = osal_procopen,
|
||||
.read = seq_read,
|
||||
.write = osal_procwrite,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release
|
||||
};
|
||||
#else
|
||||
struct proc_ops osal_proc_ops = {
|
||||
.proc_open = osal_procopen,
|
||||
.proc_read = seq_read,
|
||||
.proc_write = osal_procwrite,
|
||||
.proc_lseek = seq_lseek,
|
||||
.proc_release = single_release
|
||||
};
|
||||
#endif
|
||||
|
||||
osal_proc_entry_t *osal_create_proc(const char *name, osal_proc_entry_t *parent)
|
||||
{
|
||||
struct proc_dir_entry *entry = NULL;
|
||||
osal_proc_entry_t *sentry = NULL;
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0)
|
||||
if (parent == NULL) {
|
||||
osal_printk("%s - parent is NULL!\n", __FUNCTION__);
|
||||
entry = create_proc_entry(name, 0, NULL);
|
||||
} else {
|
||||
osal_printk("%s - parent is not NULL! parent=%pK\n", __FUNCTION__, parent->proc_dir_entry);
|
||||
entry = create_proc_entry(name, 0, parent->proc_dir_entry);
|
||||
}
|
||||
if (entry == NULL) {
|
||||
osal_printk("%s - create_proc_entry failed!\n", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
sentry = kmalloc(sizeof(struct osal_proc_dir_entry), GFP_KERNEL);
|
||||
if (sentry == NULL) {
|
||||
if (parent != NULL) {
|
||||
remove_proc_entry(name, parent->proc_dir_entry);
|
||||
} else {
|
||||
remove_proc_entry(name, NULL);
|
||||
}
|
||||
osal_printk("%s - kmalloc failed!\n", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
osal_memset(sentry, 0, sizeof(struct osal_proc_dir_entry));
|
||||
|
||||
osal_strncpy(sentry->name, name, sizeof(sentry->name) - 1);
|
||||
sentry->proc_dir_entry = entry;
|
||||
sentry->open = NULL;
|
||||
entry->proc_fops = &osal_proc_ops;
|
||||
entry->data = sentry;
|
||||
#else
|
||||
sentry = kmalloc(sizeof(struct osal_proc_dir_entry), GFP_KERNEL);
|
||||
if (sentry == NULL) {
|
||||
osal_printk("%s - kmalloc failed!\n", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
osal_memset(sentry, 0, sizeof(struct osal_proc_dir_entry));
|
||||
|
||||
osal_strncpy(sentry->name, name, sizeof(sentry->name) - 1);
|
||||
|
||||
if (parent == NULL) {
|
||||
entry = proc_create_data(name, 0, NULL, &osal_proc_ops, sentry);
|
||||
} else {
|
||||
entry = proc_create_data(name, 0, parent->proc_dir_entry, &osal_proc_ops, sentry);
|
||||
}
|
||||
if (entry == NULL) {
|
||||
osal_printk("%s - create_proc_entry failed!\n", __FUNCTION__);
|
||||
kfree(sentry);
|
||||
sentry = NULL;
|
||||
return NULL;
|
||||
}
|
||||
sentry->proc_dir_entry = entry;
|
||||
sentry->open = NULL;
|
||||
#endif
|
||||
osal_list_add_tail(&(sentry->node), &list);
|
||||
return sentry;
|
||||
}
|
||||
|
||||
void osal_remove_proc(const char *name, osal_proc_entry_t *parent)
|
||||
{
|
||||
struct osal_proc_dir_entry *sproc = NULL;
|
||||
|
||||
if (name == NULL) {
|
||||
osal_printk("%s - parameter invalid!\n", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
if (parent != NULL) {
|
||||
remove_proc_entry(name, parent->proc_dir_entry);
|
||||
} else {
|
||||
remove_proc_entry(name, NULL);
|
||||
}
|
||||
osal_list_for_each_entry(sproc, &list, node) {
|
||||
if (osal_strncmp(sproc->name, name, sizeof(sproc->name)) == 0) {
|
||||
osal_list_del(&(sproc->node));
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (sproc != NULL) {
|
||||
kfree(sproc);
|
||||
}
|
||||
}
|
||||
|
||||
osal_proc_entry_t *osal_create_proc_entry(const char *name, osal_proc_entry_t *parent)
|
||||
{
|
||||
parent = proc_entry;
|
||||
|
||||
return osal_create_proc(name, parent);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_create_proc_entry);
|
||||
|
||||
void osal_remove_proc_entry(const char *name, osal_proc_entry_t *parent)
|
||||
{
|
||||
parent = proc_entry;
|
||||
osal_remove_proc(name, parent);
|
||||
return;
|
||||
}
|
||||
EXPORT_SYMBOL(osal_remove_proc_entry);
|
||||
|
||||
osal_proc_entry_t *osal_proc_mkdir(const char *name, osal_proc_entry_t *parent)
|
||||
{
|
||||
struct proc_dir_entry *proc = NULL;
|
||||
struct osal_proc_dir_entry *sproc = NULL;
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0)
|
||||
if (parent != NULL) {
|
||||
proc = proc_mkdir(name, parent->proc_dir_entry);
|
||||
osal_printk("%s - parent is not NULL!\n", __FUNCTION__);
|
||||
// proc = create_proc_entry(name, S_IFDIR | S_IRUGO | S_IXUGO, parent->proc_dir_entry);
|
||||
} else {
|
||||
proc = proc_mkdir(name, NULL);
|
||||
osal_printk("%s - parent is NULL! proc=%pK \n", __FUNCTION__, proc);
|
||||
// proc = create_proc_entry(name, S_IFDIR | S_IRUGO | S_IXUGO, NULL);
|
||||
}
|
||||
if (proc == NULL) {
|
||||
osal_printk("%s - proc_mkdir failed!\n", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
// osal_memset(proc, 0x00, sizeof(proc));
|
||||
sproc = kmalloc(sizeof(struct osal_proc_dir_entry), GFP_KERNEL);
|
||||
if (sproc == NULL) {
|
||||
if (parent != NULL) {
|
||||
remove_proc_entry(name, parent->proc_dir_entry);
|
||||
} else {
|
||||
remove_proc_entry(name, NULL);
|
||||
}
|
||||
osal_printk("%s - kmalloc failed!\n", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
osal_memset(sproc, 0, sizeof(struct osal_proc_dir_entry));
|
||||
|
||||
osal_strncpy(sproc->name, name, sizeof(sproc->name) - 1);
|
||||
sproc->proc_dir_entry = proc;
|
||||
// sproc->read = NULL;
|
||||
// sproc->write = NULL;
|
||||
// proc->proc_fops = NULL;
|
||||
proc->data = sproc;
|
||||
#else
|
||||
sproc = kmalloc(sizeof(struct osal_proc_dir_entry), GFP_KERNEL);
|
||||
if (sproc == NULL) {
|
||||
osal_printk("%s - kmalloc failed!\n", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
osal_memset(sproc, 0, sizeof(struct osal_proc_dir_entry));
|
||||
|
||||
osal_strncpy(sproc->name, name, sizeof(sproc->name) - 1);
|
||||
|
||||
if (parent != NULL) {
|
||||
proc = proc_mkdir_data(name, 0, parent->proc_dir_entry, sproc);
|
||||
} else {
|
||||
proc = proc_mkdir_data(name, 0, NULL, sproc);
|
||||
}
|
||||
if (proc == NULL) {
|
||||
osal_printk("%s - proc_mkdir failed!\n", __FUNCTION__);
|
||||
kfree(sproc);
|
||||
sproc = NULL;
|
||||
return NULL;
|
||||
}
|
||||
sproc->proc_dir_entry = proc;
|
||||
#endif
|
||||
osal_list_add_tail(&(sproc->node), &list);
|
||||
return sproc;
|
||||
}
|
||||
EXPORT_SYMBOL(osal_proc_mkdir);
|
||||
|
||||
void osal_remove_proc_root(const char *name, osal_proc_entry_t *parent)
|
||||
{
|
||||
struct osal_proc_dir_entry *sproc = NULL;
|
||||
if (name == NULL) {
|
||||
osal_printk("%s - parameter invalid!\n", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
if (parent != NULL) {
|
||||
remove_proc_entry(name, parent->proc_dir_entry);
|
||||
} else {
|
||||
remove_proc_entry(name, NULL);
|
||||
}
|
||||
osal_list_for_each_entry(sproc, &list, node) {
|
||||
if (osal_strncmp(sproc->name, name, sizeof(sproc->name)) == 0) {
|
||||
osal_list_del(&(sproc->node));
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (sproc != NULL) {
|
||||
kfree(sproc);
|
||||
}
|
||||
}
|
||||
|
||||
void osal_seq_printf(osal_proc_entry_t *entry, const char *fmt, ...)
|
||||
{
|
||||
struct seq_file *s = (struct seq_file *)(entry->seqfile);
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 3, 0)
|
||||
(void)seq_vprintf(s, fmt, args);
|
||||
#else
|
||||
seq_vprintf(s, fmt, args);
|
||||
#endif
|
||||
va_end(args);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_seq_printf);
|
||||
|
||||
void osal_proc_init(void)
|
||||
{
|
||||
OSAL_INIT_LIST_HEAD(&list);
|
||||
proc_entry = osal_proc_mkdir("umap", OSAL_NULL);
|
||||
if (proc_entry == OSAL_NULL) {
|
||||
osal_printk("test init, proc mkdir error!\n");
|
||||
}
|
||||
}
|
||||
void osal_proc_exit(void)
|
||||
{
|
||||
osal_remove_proc_root("umap", OSAL_NULL);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright (c) XMEDIA. All rights reserved.
|
||||
*/
|
||||
#include "osal.h"
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/sched.h>
|
||||
|
||||
void osal_yield(void)
|
||||
{
|
||||
// yield();
|
||||
cond_resched();
|
||||
}
|
||||
EXPORT_SYMBOL(osal_yield);
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (c) XMEDIA. All rights reserved.
|
||||
*/
|
||||
#include "osal.h"
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/printk.h>
|
||||
#include <linux/semaphore.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
int osal_sema_init(osal_semaphore_t *sem, int val)
|
||||
{
|
||||
struct semaphore *p = NULL;
|
||||
if (sem == NULL) {
|
||||
osal_printk("%s - parameter invalid!\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
p = kmalloc(sizeof(struct semaphore), GFP_KERNEL);
|
||||
if (p == NULL) {
|
||||
osal_printk("%s - kmalloc error!\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
sema_init(p, val);
|
||||
sem->sem = p;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(osal_sema_init);
|
||||
|
||||
int osal_down(osal_semaphore_t *sem)
|
||||
{
|
||||
struct semaphore *p = NULL;
|
||||
if (sem == NULL) {
|
||||
osal_printk("%s - parameter invalid!\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
p = (struct semaphore *)(sem->sem);
|
||||
down(p);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(osal_down);
|
||||
|
||||
int osal_down_interruptible(osal_semaphore_t *sem)
|
||||
{
|
||||
struct semaphore *p = NULL;
|
||||
if (sem == NULL) {
|
||||
osal_printk("%s - parameter invalid!\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
p = (struct semaphore *)(sem->sem);
|
||||
return down_interruptible(p);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_down_interruptible);
|
||||
|
||||
int osal_down_trylock(osal_semaphore_t *sem)
|
||||
{
|
||||
struct semaphore *p = NULL;
|
||||
if (sem == NULL) {
|
||||
osal_printk("%s - parameter invalid!\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
p = (struct semaphore *)(sem->sem);
|
||||
return down_trylock(p);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_down_trylock);
|
||||
|
||||
void osal_up(osal_semaphore_t *sem)
|
||||
{
|
||||
struct semaphore *p = NULL;
|
||||
p = (struct semaphore *)(sem->sem);
|
||||
up(p);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_up);
|
||||
|
||||
void osal_sema_destory(osal_semaphore_t *sem)
|
||||
{
|
||||
if((sem != NULL) && (sem->sem != NULL)) {
|
||||
kfree((struct semaphore *)(sem->sem));
|
||||
sem->sem = NULL;
|
||||
} else {
|
||||
osal_printk("%s - parameter invalid!\n", __FUNCTION__);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(osal_sema_destory);
|
||||
|
||||
void osal_sema_destroy(osal_semaphore_t *sem)
|
||||
{
|
||||
if((sem != NULL) && (sem->sem != NULL)) {
|
||||
kfree((struct semaphore *)(sem->sem));
|
||||
sem->sem = NULL;
|
||||
} else {
|
||||
osal_printk("%s - parameter invalid!\n", __FUNCTION__);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(osal_sema_destroy);
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright (c) XMEDIA. All rights reserved.
|
||||
*/
|
||||
#include "osal.h"
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/printk.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
int osal_spin_lock_init(osal_spinlock_t *lock)
|
||||
{
|
||||
spinlock_t *p = NULL;
|
||||
if (lock == NULL) {
|
||||
osal_printk("%s - parameter invalid!\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
p = (spinlock_t *)kmalloc(sizeof(spinlock_t), GFP_KERNEL);
|
||||
if (p == NULL) {
|
||||
osal_printk("%s - kmalloc error!\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
spin_lock_init(p);
|
||||
lock->lock = p;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(osal_spin_lock_init);
|
||||
|
||||
void osal_spin_lock(osal_spinlock_t *lock)
|
||||
{
|
||||
spinlock_t *p = NULL;
|
||||
|
||||
p = (spinlock_t *)(lock->lock);
|
||||
spin_lock(p);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_spin_lock);
|
||||
|
||||
int osal_spin_trylock(osal_spinlock_t *lock)
|
||||
{
|
||||
spinlock_t *p = NULL;
|
||||
if (lock == NULL) {
|
||||
osal_printk("%s - parameter invalid!\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
p = (spinlock_t *)(lock->lock);
|
||||
return spin_trylock(p);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_spin_trylock);
|
||||
|
||||
void osal_spin_unlock(osal_spinlock_t *lock)
|
||||
{
|
||||
spinlock_t *p = NULL;
|
||||
|
||||
p = (spinlock_t *)(lock->lock);
|
||||
spin_unlock(p);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_spin_unlock);
|
||||
|
||||
void osal_spin_lock_irqsave(osal_spinlock_t *lock, unsigned long *flags)
|
||||
{
|
||||
spinlock_t *p = NULL;
|
||||
unsigned long f;
|
||||
|
||||
p = (spinlock_t *)(lock->lock);
|
||||
spin_lock_irqsave(p, f);
|
||||
*flags = f;
|
||||
}
|
||||
EXPORT_SYMBOL(osal_spin_lock_irqsave);
|
||||
void osal_spin_unlock_irqrestore(osal_spinlock_t *lock, unsigned long *flags)
|
||||
{
|
||||
spinlock_t *p = NULL;
|
||||
unsigned long f;
|
||||
|
||||
p = (spinlock_t *)(lock->lock);
|
||||
f = *flags;
|
||||
spin_unlock_irqrestore(p, f);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_spin_unlock_irqrestore);
|
||||
|
||||
void osal_spin_lock_destory(osal_spinlock_t *lock)
|
||||
{
|
||||
if((lock != NULL) && (lock->lock != NULL)) {
|
||||
kfree((spinlock_t *)(lock->lock));
|
||||
lock->lock = NULL;
|
||||
} else {
|
||||
osal_printk("%s - parameter invalid!\n", __FUNCTION__);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(osal_spin_lock_destory);
|
||||
|
||||
void osal_spin_lock_destroy(osal_spinlock_t *lock)
|
||||
{
|
||||
if((lock != NULL) && (lock->lock != NULL)) {
|
||||
kfree((spinlock_t *)(lock->lock));
|
||||
lock->lock = NULL;
|
||||
} else {
|
||||
osal_printk("%s - parameter invalid!\n", __FUNCTION__);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(osal_spin_lock_destroy);
|
||||
|
||||
@@ -0,0 +1,235 @@
|
||||
/*
|
||||
* Copyright (c) XMEDIA. All rights reserved.
|
||||
*/
|
||||
#include "osal.h"
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/printk.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/version.h>
|
||||
|
||||
char *osal_strcpy(char *dest, const char *src)
|
||||
{
|
||||
return strcpy(dest, src);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_strcpy);
|
||||
char *osal_strncpy(char *dest, const char *src, int count)
|
||||
{
|
||||
return strncpy(dest, src, count);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_strncpy);
|
||||
int osal_strlcpy(char *dest, const char *src, int size)
|
||||
{
|
||||
return strlcpy(dest, src, size);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_strlcpy);
|
||||
char *osal_strcat(char *dest, const char *src)
|
||||
{
|
||||
return strcat(dest, src);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_strcat);
|
||||
char *osal_strncat(char *dest, const char *src, int count)
|
||||
{
|
||||
return strncat(dest, src, count);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_strncat);
|
||||
int osal_strlcat(char *dest, const char *src, int count)
|
||||
{
|
||||
return strlcat(dest, src, count);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_strlcat);
|
||||
int osal_strcmp(const char *cs, const char *ct)
|
||||
{
|
||||
return strcmp(cs, ct);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_strcmp);
|
||||
int osal_strncmp(const char *cs, const char *ct, int count)
|
||||
{
|
||||
return strncmp(cs, ct, count);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_strncmp);
|
||||
int osal_strnicmp(const char *s1, const char *s2, int len)
|
||||
{
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)
|
||||
return strnicmp(s1, s2, len);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(osal_strnicmp);
|
||||
int osal_strcasecmp(const char *s1, const char *s2)
|
||||
{
|
||||
return strcasecmp(s1, s2);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_strcasecmp);
|
||||
int osal_strncasecmp(const char *s1, const char *s2, int n)
|
||||
{
|
||||
return strncasecmp(s1, s2, n);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_strncasecmp);
|
||||
char *osal_strchr(const char *s, int c)
|
||||
{
|
||||
return strchr(s, c);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_strchr);
|
||||
char *osal_strnchr(const char *s, int count, int c)
|
||||
{
|
||||
return strnchr(s, count, c);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_strnchr);
|
||||
char *osal_strrchr(const char *s, int c)
|
||||
{
|
||||
return strrchr(s, c);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_strrchr);
|
||||
char *osal_strstr(const char *s1, const char *s2)
|
||||
{
|
||||
return strstr(s1, s2);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_strstr);
|
||||
char *osal_strnstr(const char *s1, const char *s2, int len)
|
||||
{
|
||||
return strnstr(s1, s2, len);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_strnstr);
|
||||
int osal_strlen(const char *s)
|
||||
{
|
||||
return strlen(s);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_strlen);
|
||||
int osal_strnlen(const char *s, int count)
|
||||
{
|
||||
return strnlen(s, count);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_strnlen);
|
||||
char *osal_strpbrk(const char *cs, const char *ct)
|
||||
{
|
||||
return strpbrk(cs, ct);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_strpbrk);
|
||||
char *osal_strsep(char **s, const char *ct)
|
||||
{
|
||||
return strsep(s, ct);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_strsep);
|
||||
int osal_strspn(const char *s, const char *accept)
|
||||
{
|
||||
return strspn(s, accept);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_strspn);
|
||||
int osal_strcspn(const char *s, const char *reject)
|
||||
{
|
||||
return strcspn(s, reject);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_strcspn);
|
||||
void *osal_memset(void *str, int c, int count)
|
||||
{
|
||||
return memset(str, c, count);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_memset);
|
||||
void *osal_memcpy(void *dest, const void *src, int count)
|
||||
{
|
||||
return memcpy(dest, src, count);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_memcpy);
|
||||
void *osal_memmove(void *dest, const void *src, int count)
|
||||
{
|
||||
return memmove(dest, src, count);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_memmove);
|
||||
void *osal_memscan(void *addr, int c, int size)
|
||||
{
|
||||
return memscan(addr, c, size);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_memscan);
|
||||
int osal_memcmp(const void *cs, const void *ct, int count)
|
||||
{
|
||||
return memcmp(cs, ct, count);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_memcmp);
|
||||
void *osal_memchr(const void *s, int c, int n)
|
||||
{
|
||||
return memchr(s, c, n);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_memchr);
|
||||
void *osal_memchr_inv(const void *start, int c, int bytes)
|
||||
{
|
||||
return memchr_inv(start, c, bytes);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_memchr_inv);
|
||||
unsigned long long osal_strtoull(const char *cp, char **endp, unsigned int base)
|
||||
{
|
||||
return simple_strtoull(cp, endp, base);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_strtoull);
|
||||
unsigned long osal_strtoul(const char *cp, char **endp, unsigned int base)
|
||||
{
|
||||
return simple_strtoul(cp, endp, base);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_strtoul);
|
||||
long osal_strtol(const char *cp, char **endp, unsigned int base)
|
||||
{
|
||||
return simple_strtol(cp, endp, base);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_strtol);
|
||||
long long osal_strtoll(const char *cp, char **endp, unsigned int base)
|
||||
{
|
||||
return simple_strtoll(cp, endp, base);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_strtoll);
|
||||
int osal_snprintf(char *buf, int size, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
int i;
|
||||
|
||||
va_start(args, fmt);
|
||||
i = vsnprintf(buf, size, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
return i;
|
||||
}
|
||||
EXPORT_SYMBOL(osal_snprintf);
|
||||
int osal_scnprintf(char *buf, int size, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
int i;
|
||||
|
||||
va_start(args, fmt);
|
||||
i = vscnprintf(buf, size, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
return i;
|
||||
}
|
||||
EXPORT_SYMBOL(osal_scnprintf);
|
||||
int osal_sprintf(char *buf, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
int i;
|
||||
|
||||
va_start(args, fmt);
|
||||
i = vsnprintf(buf, INT_MAX, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
return i;
|
||||
}
|
||||
EXPORT_SYMBOL(osal_sprintf);
|
||||
int osal_sscanf(const char *buf, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
int i;
|
||||
|
||||
va_start(args, fmt);
|
||||
i = vsscanf(buf, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
return i;
|
||||
}
|
||||
EXPORT_SYMBOL(osal_sscanf);
|
||||
|
||||
int osal_vsnprintf(char *str, int size, const char *fmt, osal_va_list args)
|
||||
{
|
||||
return vsnprintf(str, size, fmt, args);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_vsnprintf);
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (c) XMEDIA. All rights reserved.
|
||||
*/
|
||||
#include "osal.h"
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/printk.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
osal_task_t *osal_kthread_create(threadfn_t thread, void *data, const char *name)
|
||||
{
|
||||
struct task_struct *k = NULL;
|
||||
osal_task_t *p = (osal_task_t *)kmalloc(sizeof(osal_task_t), GFP_KERNEL);
|
||||
if (p == NULL) {
|
||||
osal_printk("%s - kmalloc error!\n", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
memset(p, 0, sizeof(osal_task_t));
|
||||
|
||||
k = kthread_run(thread, data, name);
|
||||
if (IS_ERR(k)) {
|
||||
osal_printk("%s - kthread create error!\n", __FUNCTION__);
|
||||
kfree(p);
|
||||
return NULL;
|
||||
}
|
||||
p->task_struct = k;
|
||||
return p;
|
||||
}
|
||||
EXPORT_SYMBOL(osal_kthread_create);
|
||||
|
||||
void osal_kthread_destory(osal_task_t *task, unsigned int stop_flag)
|
||||
{
|
||||
if (task == NULL) {
|
||||
osal_printk("%s - parameter invalid!\n", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
/* note: When you call the Kthread_stop function, the thread function cannot be finished, otherwise it will oops. */
|
||||
if (stop_flag != 0) {
|
||||
kthread_stop ((struct task_struct *)(task->task_struct));
|
||||
}
|
||||
task->task_struct = NULL;
|
||||
kfree(task);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_kthread_destory);
|
||||
|
||||
void osal_kthread_destroy(osal_task_t *task, unsigned int stop_flag)
|
||||
{
|
||||
if (task == NULL) {
|
||||
osal_printk("%s - parameter invalid!\n", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
/* note: When you call the Kthread_stop function, the thread function cannot be finished, otherwise it will oops. */
|
||||
if (stop_flag != 0) {
|
||||
kthread_stop ((struct task_struct *)(task->task_struct));
|
||||
}
|
||||
task->task_struct = NULL;
|
||||
kfree(task);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_kthread_destroy);
|
||||
|
||||
int osal_kthread_should_stop(void)
|
||||
{
|
||||
return kthread_should_stop();
|
||||
}
|
||||
EXPORT_SYMBOL(osal_kthread_should_stop);
|
||||
@@ -0,0 +1,298 @@
|
||||
/*
|
||||
* Copyright (c) XMEDIA. All rights reserved.
|
||||
*/
|
||||
#include <linux/version.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/printk.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/rtc.h>
|
||||
#if LINUX_VERSION_CODE > KERNEL_VERSION(4, 19, 0)
|
||||
#include <linux/sched/clock.h>
|
||||
#endif
|
||||
#include "osal.h"
|
||||
|
||||
#if LINUX_VERSION_CODE > KERNEL_VERSION(4, 19, 0)
|
||||
struct timer_list_info {
|
||||
struct timer_list time_list;
|
||||
unsigned long data;
|
||||
};
|
||||
typedef void (*timer_callback_fun)(struct timer_list * data);
|
||||
#endif
|
||||
|
||||
int osal_hrtimer_create(osal_hrtimer_t *phrtimer)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
EXPORT_SYMBOL(osal_hrtimer_create);
|
||||
|
||||
int osal_hrtimer_start(osal_hrtimer_t *phrtimer)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
EXPORT_SYMBOL(osal_hrtimer_start);
|
||||
|
||||
int osal_hrtimer_destroy(osal_hrtimer_t *phrtimer)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
EXPORT_SYMBOL(osal_hrtimer_destroy);
|
||||
|
||||
unsigned long osal_timer_get_private_data(void *data)
|
||||
{
|
||||
#if LINUX_VERSION_CODE > KERNEL_VERSION(4, 19, 0)
|
||||
struct timer_list_info *list_info = osal_container_of(data, struct timer_list_info, time_list);
|
||||
|
||||
return list_info->data;
|
||||
#else
|
||||
return (unsigned long)data;
|
||||
#endif
|
||||
}
|
||||
EXPORT_SYMBOL(osal_timer_get_private_data);
|
||||
|
||||
#if LINUX_VERSION_CODE > KERNEL_VERSION(4, 19, 0)
|
||||
int osal_timer_init(osal_timer_t *timer)
|
||||
{
|
||||
struct timer_list_info *t = NULL;
|
||||
|
||||
if (timer == NULL) {
|
||||
osal_printk("%s - parameter invalid!\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
t = (struct timer_list_info *)kmalloc(sizeof(struct timer_list_info), GFP_KERNEL);
|
||||
if (t == NULL) {
|
||||
osal_printk("%s - kmalloc error!\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
t->data = timer->data;
|
||||
timer_setup(&t->time_list, (timer_callback_fun)timer->function, 0);
|
||||
timer->timer = t;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(osal_timer_init);
|
||||
|
||||
int osal_set_timer(osal_timer_t *timer, unsigned long interval)
|
||||
{
|
||||
struct timer_list_info *list_info = NULL;
|
||||
if ((timer == NULL) || (timer->timer == NULL) || (timer->function == NULL) || (interval == 0)) {
|
||||
osal_printk("%s - parameter invalid!\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
list_info = (struct timer_list_info *)timer->timer;
|
||||
list_info->data = timer->data;
|
||||
list_info->time_list.function = (timer_callback_fun)timer->function;
|
||||
return mod_timer(&list_info->time_list, jiffies + msecs_to_jiffies(interval) - 1);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_set_timer);
|
||||
#else
|
||||
int osal_timer_init(osal_timer_t *timer)
|
||||
{
|
||||
struct timer_list *t = NULL;
|
||||
|
||||
if (timer == NULL) {
|
||||
osal_printk("%s - parameter invalid!\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
t = (struct timer_list *)kmalloc(sizeof(struct timer_list), GFP_KERNEL);
|
||||
if (t == NULL) {
|
||||
osal_printk("%s - kmalloc error!\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
init_timer(t);
|
||||
timer->timer = t;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(osal_timer_init);
|
||||
|
||||
int osal_set_timer(osal_timer_t *timer, unsigned long interval)
|
||||
{
|
||||
struct timer_list *t = NULL;
|
||||
if ((timer == NULL) || (timer->timer == NULL) || (timer->function == NULL) || (interval == 0)) {
|
||||
osal_printk("%s - parameter invalid!\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
t = timer->timer;
|
||||
t->function = timer->function;
|
||||
t->data = timer->data;
|
||||
return mod_timer(t, jiffies + msecs_to_jiffies(interval) - 1);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_set_timer);
|
||||
#endif
|
||||
|
||||
int osal_del_timer(osal_timer_t *timer)
|
||||
{
|
||||
struct timer_list *t = NULL;
|
||||
if ((timer == NULL) || (timer->timer == NULL) || (timer->function == NULL)) {
|
||||
osal_printk("%s - parameter invalid!\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
t = timer->timer;
|
||||
return del_timer(t);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_del_timer);
|
||||
|
||||
int osal_timer_destory(osal_timer_t *timer)
|
||||
{
|
||||
struct timer_list *t = NULL;
|
||||
if ((timer == NULL) || (timer->timer == NULL)) {
|
||||
osal_printk("%s - parameter invalid!\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
t = timer->timer;
|
||||
del_timer(t);
|
||||
kfree(t);
|
||||
timer->timer = NULL;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(osal_timer_destory);
|
||||
|
||||
int osal_timer_destroy(osal_timer_t *timer)
|
||||
{
|
||||
struct timer_list *t = NULL;
|
||||
if ((timer == NULL) || (timer->timer == NULL)) {
|
||||
osal_printk("%s - parameter invalid!\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
t = timer->timer;
|
||||
del_timer(t);
|
||||
kfree(t);
|
||||
timer->timer = NULL;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(osal_timer_destroy);
|
||||
|
||||
unsigned long osal_msleep(unsigned int msecs)
|
||||
{
|
||||
return msleep_interruptible(msecs);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_msleep);
|
||||
|
||||
void osal_udelay(unsigned int usecs)
|
||||
{
|
||||
udelay(usecs);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_udelay);
|
||||
|
||||
void osal_mdelay(unsigned int msecs)
|
||||
{
|
||||
mdelay(msecs);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_mdelay);
|
||||
|
||||
unsigned int osal_get_tickcount()
|
||||
{
|
||||
return jiffies_to_msecs(jiffies);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_get_tickcount);
|
||||
|
||||
unsigned long long osal_sched_clock()
|
||||
{
|
||||
return sched_clock();
|
||||
}
|
||||
EXPORT_SYMBOL(osal_sched_clock);
|
||||
|
||||
void osal_gettimeofday(osal_timeval_t *tv)
|
||||
{
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0)
|
||||
struct timeval t;
|
||||
if (tv == NULL) {
|
||||
osal_printk("%s - parameter invalid!\n", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
do_gettimeofday(&t);
|
||||
|
||||
tv->tv_sec = t.tv_sec;
|
||||
tv->tv_usec = t.tv_usec;
|
||||
#else
|
||||
struct timespec64 t;
|
||||
if (tv == NULL) {
|
||||
osal_printk("%s - parameter invalid!\n", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
ktime_get_real_ts64(&t);
|
||||
|
||||
tv->tv_sec = (long)(t.tv_sec);
|
||||
tv->tv_usec = t.tv_nsec / 1000;
|
||||
#endif
|
||||
}
|
||||
EXPORT_SYMBOL(osal_gettimeofday);
|
||||
|
||||
unsigned long long osal_get_boottime(void)
|
||||
{
|
||||
return ktime_to_ns(ktime_get_boottime());
|
||||
}
|
||||
EXPORT_SYMBOL(osal_get_boottime);
|
||||
|
||||
void osal_rtc_time_to_tm(unsigned long time, osal_rtc_time_t *tm)
|
||||
{
|
||||
struct rtc_time _tm = { 0 };
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0)
|
||||
rtc_time_to_tm(time, &_tm);
|
||||
#else
|
||||
rtc_time64_to_tm((time64_t)time, &_tm);
|
||||
#endif
|
||||
tm->tm_sec = _tm.tm_sec;
|
||||
tm->tm_min = _tm.tm_min;
|
||||
tm->tm_hour = _tm.tm_hour;
|
||||
tm->tm_mday = _tm.tm_mday;
|
||||
tm->tm_mon = _tm.tm_mon;
|
||||
tm->tm_year = _tm.tm_year;
|
||||
tm->tm_wday = _tm.tm_wday;
|
||||
tm->tm_yday = _tm.tm_yday;
|
||||
tm->tm_isdst = _tm.tm_isdst;
|
||||
}
|
||||
EXPORT_SYMBOL(osal_rtc_time_to_tm);
|
||||
|
||||
void osal_rtc_tm_to_time(osal_rtc_time_t *tm, unsigned long *time)
|
||||
{
|
||||
struct rtc_time _tm;
|
||||
_tm.tm_sec = tm->tm_sec;
|
||||
_tm.tm_min = tm->tm_min;
|
||||
_tm.tm_hour = tm->tm_hour;
|
||||
_tm.tm_mday = tm->tm_mday;
|
||||
_tm.tm_mon = tm->tm_mon;
|
||||
_tm.tm_year = tm->tm_year;
|
||||
_tm.tm_wday = tm->tm_wday;
|
||||
_tm.tm_yday = tm->tm_yday;
|
||||
_tm.tm_isdst = tm->tm_isdst;
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 10, 0)
|
||||
rtc_tm_to_time(&_tm, time);
|
||||
#else
|
||||
*time = (unsigned long)rtc_tm_to_time64(&_tm);
|
||||
#endif
|
||||
}
|
||||
EXPORT_SYMBOL(osal_rtc_tm_to_time);
|
||||
|
||||
void osal_getjiffies(unsigned long long *pjiffies)
|
||||
{
|
||||
*pjiffies = jiffies;
|
||||
}
|
||||
EXPORT_SYMBOL(osal_getjiffies);
|
||||
|
||||
int osal_rtc_valid_tm(struct osal_rtc_time *tm)
|
||||
{
|
||||
struct rtc_time _tm;
|
||||
_tm.tm_sec = tm->tm_sec;
|
||||
_tm.tm_min = tm->tm_min;
|
||||
_tm.tm_hour = tm->tm_hour;
|
||||
_tm.tm_mday = tm->tm_mday;
|
||||
_tm.tm_mon = tm->tm_mon;
|
||||
_tm.tm_year = tm->tm_year;
|
||||
_tm.tm_wday = tm->tm_wday;
|
||||
_tm.tm_yday = tm->tm_yday;
|
||||
_tm.tm_isdst = tm->tm_isdst;
|
||||
|
||||
return rtc_valid_tm(&_tm);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_rtc_valid_tm);
|
||||
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) XMEDIA. All rights reserved.
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/slab.h>
|
||||
#include "osal.h"
|
||||
|
||||
void *osal_vmalloc(unsigned long size)
|
||||
{
|
||||
return vmalloc(size);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_vmalloc);
|
||||
|
||||
void osal_vfree(const void *addr)
|
||||
{
|
||||
vfree(addr);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_vfree);
|
||||
|
||||
void *osal_kmalloc(unsigned long size, unsigned int osal_gfp_flag)
|
||||
{
|
||||
if (osal_gfp_flag == osal_gfp_kernel) {
|
||||
return kmalloc(size, GFP_KERNEL);
|
||||
} else if (osal_gfp_flag == osal_gfp_atomic) {
|
||||
return kmalloc(size, GFP_ATOMIC);
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(osal_kmalloc);
|
||||
|
||||
void osal_kfree(const void *addr)
|
||||
{
|
||||
kfree(addr);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(osal_kfree);
|
||||
|
||||
|
||||
@@ -0,0 +1,217 @@
|
||||
/*
|
||||
* Copyright (c) XMEDIA. All rights reserved.
|
||||
*/
|
||||
#include "osal.h"
|
||||
#include <linux/version.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/printk.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/sched.h>
|
||||
#if LINUX_VERSION_CODE > KERNEL_VERSION(4, 19, 0)
|
||||
#include <linux/sched/signal.h>
|
||||
#endif
|
||||
#include <linux/slab.h>
|
||||
|
||||
unsigned long osal_msecs_to_jiffies(const unsigned int m)
|
||||
{
|
||||
return msecs_to_jiffies(m);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_msecs_to_jiffies);
|
||||
|
||||
int osal_wait_init(osal_wait_t *wait)
|
||||
{
|
||||
wait_queue_head_t *wq = NULL;
|
||||
if (wait == NULL) {
|
||||
osal_printk("%s - parameter invalid!\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
wq = (wait_queue_head_t *)kmalloc(sizeof(wait_queue_head_t), GFP_ATOMIC);
|
||||
if (wq == NULL) {
|
||||
osal_printk("%s - kmalloc error!\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
init_waitqueue_head(wq);
|
||||
wait->wait = wq;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(osal_wait_init);
|
||||
|
||||
int osal_wait_interruptible(osal_wait_t *wait, osal_wait_cond_func_t func, void *param)
|
||||
{
|
||||
wait_queue_head_t *wq = NULL;
|
||||
DEFINE_WAIT(__wait);
|
||||
long ret = 0;
|
||||
int condition = 0;
|
||||
|
||||
if (wait == NULL) {
|
||||
osal_printk("%s - parameter invalid!\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
wq = (wait_queue_head_t *)(wait->wait);
|
||||
if (wq == NULL) {
|
||||
osal_printk("%s - wait->wait is NULL!\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
prepare_to_wait(wq, &__wait, TASK_INTERRUPTIBLE);
|
||||
/* if wakeup the queue brefore prepare_to_wait, the func will return true. And will not go to schedule */
|
||||
if (func != NULL) {
|
||||
condition = func(param);
|
||||
}
|
||||
|
||||
if (!condition) {
|
||||
if (!signal_pending(current)) {
|
||||
schedule();
|
||||
}
|
||||
if (signal_pending(current)) {
|
||||
ret = -ERESTARTSYS;
|
||||
}
|
||||
}
|
||||
|
||||
finish_wait(wq, &__wait);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(osal_wait_interruptible);
|
||||
|
||||
int osal_wait_uninterruptible(osal_wait_t *wait, osal_wait_cond_func_t func, void *param)
|
||||
{
|
||||
wait_queue_head_t *wq = NULL;
|
||||
DEFINE_WAIT(__wait);
|
||||
long ret = 0;
|
||||
int condition = 0;
|
||||
|
||||
if (wait == NULL) {
|
||||
osal_printk("%s - parameter invalid!\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
wq = (wait_queue_head_t *)(wait->wait);
|
||||
if (wq == NULL) {
|
||||
osal_printk("%s - wait->wait is NULL!\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
prepare_to_wait(wq, &__wait, TASK_UNINTERRUPTIBLE);
|
||||
/* if wakeup the queue brefore prepare_to_wait, the func will return true. And will not go to schedule */
|
||||
if (func != NULL) {
|
||||
condition = func(param);
|
||||
}
|
||||
|
||||
if (!condition) {
|
||||
schedule();
|
||||
}
|
||||
|
||||
finish_wait(wq, &__wait);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(osal_wait_uninterruptible);
|
||||
|
||||
int osal_wait_timeout_interruptible(osal_wait_t *wait, osal_wait_cond_func_t func, void *param, unsigned long ms)
|
||||
{
|
||||
wait_queue_head_t *wq = NULL;
|
||||
DEFINE_WAIT(__wait);
|
||||
long ret = ms;
|
||||
int condition = 0;
|
||||
|
||||
if (wait == NULL) {
|
||||
osal_printk("%s - parameter invalid!\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
wq = (wait_queue_head_t *)(wait->wait);
|
||||
if (wq == NULL) {
|
||||
osal_printk("%s - wait->wait is NULL!\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
prepare_to_wait(wq, &__wait, TASK_INTERRUPTIBLE);
|
||||
/* if wakeup the queue brefore prepare_to_wait, the func will return true. And will not go to schedule */
|
||||
if (func != NULL) {
|
||||
condition = func(param);
|
||||
}
|
||||
|
||||
if (!condition) {
|
||||
if (!signal_pending(current)) {
|
||||
ret = schedule_timeout(msecs_to_jiffies(ret));
|
||||
ret = jiffies_to_msecs(ret);
|
||||
}
|
||||
if (signal_pending(current)) {
|
||||
ret = -ERESTARTSYS;
|
||||
}
|
||||
}
|
||||
|
||||
finish_wait(wq, &__wait);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(osal_wait_timeout_interruptible);
|
||||
|
||||
int osal_wait_timeout_uninterruptible(osal_wait_t *wait, osal_wait_cond_func_t func, void *param, unsigned long ms)
|
||||
{
|
||||
wait_queue_head_t *wq = NULL;
|
||||
DEFINE_WAIT(__wait);
|
||||
long ret = ms;
|
||||
int condition = 0;
|
||||
|
||||
if (wait == NULL) {
|
||||
osal_printk("%s - parameter invalid!\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
wq = (wait_queue_head_t *)(wait->wait);
|
||||
if (wq == NULL) {
|
||||
osal_printk("%s - wait->wait is NULL!\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
prepare_to_wait(wq, &__wait, TASK_UNINTERRUPTIBLE);
|
||||
/* if wakeup the queue brefore prepare_to_wait, the func will return true. And will not go to schedule */
|
||||
if (func != NULL) {
|
||||
condition = func(param);
|
||||
}
|
||||
|
||||
if (!condition) {
|
||||
ret = schedule_timeout(msecs_to_jiffies(ret));
|
||||
ret = jiffies_to_msecs(ret);
|
||||
}
|
||||
|
||||
finish_wait(wq, &__wait);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(osal_wait_timeout_uninterruptible);
|
||||
|
||||
void osal_wakeup(osal_wait_t *wait)
|
||||
{
|
||||
wait_queue_head_t *wq = NULL;
|
||||
|
||||
wq = (wait_queue_head_t *)(wait->wait);
|
||||
if (wq == NULL) {
|
||||
osal_printk("%s - wait->wait is NULL!\n", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
wake_up_all(wq);
|
||||
}
|
||||
EXPORT_SYMBOL(osal_wakeup);
|
||||
|
||||
void osal_wait_destory(osal_wait_t *wait)
|
||||
{
|
||||
if ((wait != NULL) && (wait->wait != NULL)) {
|
||||
kfree((wait_queue_head_t *)(wait->wait));
|
||||
wait->wait = NULL;
|
||||
} else {
|
||||
osal_printk("%s - wait->wait is NULL!\n", __FUNCTION__);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(osal_wait_destory);
|
||||
|
||||
void osal_wait_destroy(osal_wait_t *wait)
|
||||
{
|
||||
if ((wait != NULL) && (wait->wait != NULL)) {
|
||||
kfree((wait_queue_head_t *)(wait->wait));
|
||||
wait->wait = NULL;
|
||||
} else {
|
||||
osal_printk("%s - wait->wait is NULL!\n", __FUNCTION__);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(osal_wait_destroy);
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (c) XMEDIA. All rights reserved.
|
||||
*/
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/module.h>
|
||||
#include "osal.h"
|
||||
|
||||
OSAL_LIST_HEAD(wq_list);
|
||||
struct wq_node {
|
||||
struct osal_work_struct *osal_work;
|
||||
struct work_struct *work;
|
||||
struct osal_list_head node;
|
||||
};
|
||||
|
||||
static struct osal_work_struct *osal_find_work(struct work_struct *work)
|
||||
{
|
||||
struct osal_list_head *this = NULL;
|
||||
if (osal_list_empty(&wq_list)) {
|
||||
osal_printk("find work failed! wq_list is empty!\n");
|
||||
return NULL;
|
||||
}
|
||||
osal_list_for_each(this, &wq_list) {
|
||||
struct wq_node *ws = osal_list_entry(this, struct wq_node, node);
|
||||
if (ws->work == work) {
|
||||
return ws->osal_work;
|
||||
}
|
||||
}
|
||||
osal_printk("find work failed!\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int osal_del_work(struct work_struct *work)
|
||||
{
|
||||
struct osal_list_head *this = NULL;
|
||||
struct osal_list_head *next = NULL;
|
||||
if (osal_list_empty(&wq_list)) {
|
||||
osal_printk("find work failed! wq_list is empty!\n");
|
||||
return -1;
|
||||
}
|
||||
osal_list_for_each_safe(this, next, &wq_list) {
|
||||
struct wq_node *ws = osal_list_entry(this, struct wq_node, node);
|
||||
if (ws->work == work) {
|
||||
osal_list_del(this);
|
||||
kfree(ws);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
osal_printk("del work failed!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void osal_work_func(struct work_struct *work)
|
||||
{
|
||||
struct osal_work_struct *ow = osal_find_work(work);
|
||||
if ((ow != NULL) && (ow->func != NULL)) {
|
||||
ow->func(ow);
|
||||
}
|
||||
}
|
||||
|
||||
int osal_init_work(struct osal_work_struct *work, osal_work_func_t func)
|
||||
{
|
||||
struct work_struct *w = NULL;
|
||||
struct wq_node *w_node = NULL;
|
||||
w = kmalloc(sizeof(struct work_struct), GFP_ATOMIC);
|
||||
if (w == NULL) {
|
||||
osal_printk("osal_init_work kmalloc failed!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
w_node = kmalloc(sizeof(struct wq_node), GFP_ATOMIC);
|
||||
if (w_node == NULL) {
|
||||
osal_printk("osal_init_work kmalloc failed!\n");
|
||||
kfree(w);
|
||||
return -1;
|
||||
}
|
||||
INIT_WORK(w, osal_work_func);
|
||||
work->work = w;
|
||||
work->func = func;
|
||||
w_node->osal_work = work;
|
||||
w_node->work = w;
|
||||
osal_list_add(&(w_node->node), &wq_list);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(osal_init_work);
|
||||
|
||||
int osal_schedule_work(struct osal_work_struct *work)
|
||||
{
|
||||
if ((work != NULL) && (work->work != NULL)) {
|
||||
return (int)schedule_work(work->work);
|
||||
} else {
|
||||
return (int)false;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(osal_schedule_work);
|
||||
|
||||
void osal_destroy_work(struct osal_work_struct *work)
|
||||
{
|
||||
if ((work != NULL) && (work->work != NULL)) {
|
||||
osal_del_work(work->work);
|
||||
kfree((struct work_struct *)work->work);
|
||||
work->work = NULL;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(osal_destroy_work);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user