mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 19:30:30 +09:00
driver: rknpu: Update rknpu driver, version: 0.7.2
Signed-off-by: Felix Zeng <felix.zeng@rock-chips.com> Change-Id: I4959bf36fac74d590e651afdccba2dd2d8a856e9
This commit is contained in:
@@ -48,8 +48,8 @@ struct rknpu_debugger_list {
|
||||
* rknpu_debugger_node corresponding to the instance of this info
|
||||
* on a given &struct rknpu_debugger.
|
||||
*/
|
||||
ssize_t (*write)(struct file *file, const char __user *ubuf,
|
||||
size_t len, loff_t *offp);
|
||||
ssize_t (*write)(struct file *file, const char __user *ubuf, size_t len,
|
||||
loff_t *offp);
|
||||
/* Procfs/Debugfs private data. */
|
||||
void *data;
|
||||
};
|
||||
@@ -78,9 +78,7 @@ struct rknpu_debugger_node {
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
|
||||
int rknpu_debugger_init(struct rknpu_device *rknpu_dev);
|
||||
int rknpu_debugger_remove(struct rknpu_device *rknpu_dev);
|
||||
|
||||
|
||||
#endif /* __LINUX_RKNPU_FENCE_H_ */
|
||||
|
||||
@@ -29,10 +29,10 @@
|
||||
|
||||
#define DRIVER_NAME "rknpu"
|
||||
#define DRIVER_DESC "RKNPU driver"
|
||||
#define DRIVER_DATE "20220328"
|
||||
#define DRIVER_DATE "20220428"
|
||||
#define DRIVER_MAJOR 0
|
||||
#define DRIVER_MINOR 7
|
||||
#define DRIVER_PATCHLEVEL 0
|
||||
#define DRIVER_PATCHLEVEL 2
|
||||
|
||||
#define LOG_TAG "RKNPU"
|
||||
|
||||
@@ -135,6 +135,7 @@ struct rknpu_device {
|
||||
struct device *genpd_dev_npu2;
|
||||
bool multiple_domains;
|
||||
atomic_t power_refcount;
|
||||
atomic_t cmdline_power_refcount;
|
||||
struct delayed_work power_off_work;
|
||||
struct workqueue_struct *power_off_wq;
|
||||
bool is_powered;
|
||||
@@ -143,4 +144,6 @@ struct rknpu_device {
|
||||
ktime_t kt;
|
||||
};
|
||||
|
||||
int rknpu_action(struct rknpu_device *rknpu_dev, struct rknpu_action *args);
|
||||
|
||||
#endif /* __LINUX_RKNPU_DRV_H_ */
|
||||
|
||||
@@ -287,8 +287,6 @@ struct rknpu_action {
|
||||
#define RKNPU_IOR(nr, type) _IOR(RKNPU_IOC_MAGIC, nr, type)
|
||||
#define RKNPU_IOWR(nr, type) _IOWR(RKNPU_IOC_MAGIC, nr, type)
|
||||
|
||||
#if defined(__arm__) || defined(__aarch64__)
|
||||
|
||||
#include <drm/drm.h>
|
||||
|
||||
#define DRM_IOCTL_RKNPU_ACTION \
|
||||
@@ -314,5 +312,3 @@ struct rknpu_action {
|
||||
#define IOCTL_RKNPU_MEM_SYNC RKNPU_IOWR(RKNPU_MEM_SYNC, struct rknpu_mem_sync)
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -64,9 +64,67 @@ static int rknpu_load_show(struct seq_file *m, void *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rknpu_power_show(struct seq_file *m, void *data)
|
||||
{
|
||||
struct rknpu_debugger_node *node = m->private;
|
||||
struct rknpu_debugger *debugger = node->debugger;
|
||||
struct rknpu_device *rknpu_dev =
|
||||
container_of(debugger, struct rknpu_device, debugger);
|
||||
|
||||
if (rknpu_dev->is_powered)
|
||||
seq_puts(m, "on\n");
|
||||
else
|
||||
seq_puts(m, "off\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t rknpu_power_set(struct file *file, const char __user *ubuf,
|
||||
size_t len, loff_t *offp)
|
||||
{
|
||||
struct seq_file *priv = file->private_data;
|
||||
struct rknpu_debugger_node *node = priv->private;
|
||||
struct rknpu_debugger *debugger = node->debugger;
|
||||
struct rknpu_device *rknpu_dev =
|
||||
container_of(debugger, struct rknpu_device, debugger);
|
||||
struct rknpu_action args;
|
||||
char buf[10];
|
||||
|
||||
if (len > sizeof(buf) - 1)
|
||||
return -EINVAL;
|
||||
if (copy_from_user(buf, ubuf, len))
|
||||
return -EFAULT;
|
||||
buf[len - 1] = '\0';
|
||||
|
||||
if (strcmp(buf, "on") == 0) {
|
||||
atomic_inc(&rknpu_dev->cmdline_power_refcount);
|
||||
args.flags = RKNPU_POWER_ON;
|
||||
rknpu_action(rknpu_dev, &args);
|
||||
LOG_INFO("rknpu power is on!");
|
||||
} else if (strcmp(buf, "off") == 0) {
|
||||
if (rknpu_dev->is_powered &&
|
||||
atomic_dec_if_positive(
|
||||
&rknpu_dev->cmdline_power_refcount) >= 0) {
|
||||
atomic_sub(
|
||||
atomic_read(&rknpu_dev->cmdline_power_refcount),
|
||||
&rknpu_dev->power_refcount);
|
||||
atomic_set(&rknpu_dev->cmdline_power_refcount, 0);
|
||||
args.flags = RKNPU_POWER_OFF;
|
||||
rknpu_action(rknpu_dev, &args);
|
||||
}
|
||||
if (!rknpu_dev->is_powered)
|
||||
LOG_INFO("rknpu power is off!");
|
||||
} else {
|
||||
LOG_ERROR("rknpu power node params is invalid!");
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
struct rknpu_debugger_list rknpu_debugger_root_list[] = {
|
||||
{ "driver_version", rknpu_version_show, NULL, NULL },
|
||||
{ "load", rknpu_load_show, NULL, NULL },
|
||||
{ "power", rknpu_power_show, rknpu_power_set, NULL }
|
||||
};
|
||||
|
||||
static ssize_t rknpu_debugger_write(struct file *file, const char __user *ubuf,
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
@@ -32,9 +33,9 @@
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/devfreq_cooling.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <soc/rockchip/rockchip_iommu.h>
|
||||
|
||||
#ifndef FPGA_PLATFORM
|
||||
#include <soc/rockchip/rockchip_iommu.h>
|
||||
#include <soc/rockchip/rockchip_opp_select.h>
|
||||
#include <soc/rockchip/rockchip_system_monitor.h>
|
||||
#include <soc/rockchip/rockchip_ipa.h>
|
||||
@@ -190,8 +191,7 @@ static void rknpu_power_off_delay_work(struct work_struct *power_off_work)
|
||||
mutex_unlock(&rknpu_dev->power_lock);
|
||||
}
|
||||
|
||||
static int rknpu_action(struct rknpu_device *rknpu_dev,
|
||||
struct rknpu_action *args)
|
||||
int rknpu_action(struct rknpu_device *rknpu_dev, struct rknpu_action *args)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
|
||||
@@ -612,11 +612,15 @@ static int rknpu_power_on(struct rknpu_device *rknpu_dev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifndef FPGA_PLATFORM
|
||||
#if KERNEL_VERSION(5, 10, 0) <= LINUX_VERSION_CODE
|
||||
rockchip_monitor_volt_adjust_lock(rknpu_dev->mdev_info);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (rknpu_dev->multiple_domains) {
|
||||
if (rknpu_dev->genpd_dev_npu0) {
|
||||
#if KERNEL_VERSION(5, 4, 0) < LINUX_VERSION_CODE
|
||||
#if KERNEL_VERSION(5, 5, 0) < LINUX_VERSION_CODE
|
||||
ret = pm_runtime_resume_and_get(
|
||||
rknpu_dev->genpd_dev_npu0);
|
||||
#else
|
||||
@@ -631,7 +635,7 @@ static int rknpu_power_on(struct rknpu_device *rknpu_dev)
|
||||
}
|
||||
}
|
||||
if (rknpu_dev->genpd_dev_npu1) {
|
||||
#if KERNEL_VERSION(5, 4, 0) < LINUX_VERSION_CODE
|
||||
#if KERNEL_VERSION(5, 5, 0) < LINUX_VERSION_CODE
|
||||
ret = pm_runtime_resume_and_get(
|
||||
rknpu_dev->genpd_dev_npu1);
|
||||
#else
|
||||
@@ -646,7 +650,7 @@ static int rknpu_power_on(struct rknpu_device *rknpu_dev)
|
||||
}
|
||||
}
|
||||
if (rknpu_dev->genpd_dev_npu2) {
|
||||
#if KERNEL_VERSION(5, 4, 0) < LINUX_VERSION_CODE
|
||||
#if KERNEL_VERSION(5, 5, 0) < LINUX_VERSION_CODE
|
||||
ret = pm_runtime_resume_and_get(
|
||||
rknpu_dev->genpd_dev_npu2);
|
||||
#else
|
||||
@@ -669,7 +673,11 @@ static int rknpu_power_on(struct rknpu_device *rknpu_dev)
|
||||
}
|
||||
|
||||
out:
|
||||
#ifndef FPGA_PLATFORM
|
||||
#if KERNEL_VERSION(5, 10, 0) <= LINUX_VERSION_CODE
|
||||
rockchip_monitor_volt_adjust_unlock(rknpu_dev->mdev_info);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -677,13 +685,19 @@ out:
|
||||
static int rknpu_power_off(struct rknpu_device *rknpu_dev)
|
||||
{
|
||||
struct device *dev = rknpu_dev->dev;
|
||||
|
||||
#ifndef FPGA_PLATFORM
|
||||
int ret;
|
||||
bool val;
|
||||
|
||||
#if KERNEL_VERSION(5, 10, 0) <= LINUX_VERSION_CODE
|
||||
rockchip_monitor_volt_adjust_lock(rknpu_dev->mdev_info);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
pm_runtime_put_sync(dev);
|
||||
|
||||
#ifndef FPGA_PLATFORM
|
||||
/*
|
||||
* Because IOMMU's runtime suspend callback is asynchronous,
|
||||
* So it may be executed after the NPU is turned off after PD/CLK/VD,
|
||||
@@ -693,16 +707,21 @@ static int rknpu_power_off(struct rknpu_device *rknpu_dev)
|
||||
* If pm runtime framework can handle this issue in the future, remove
|
||||
* this.
|
||||
*/
|
||||
|
||||
ret = readx_poll_timeout(rockchip_iommu_is_enabled, dev, val,
|
||||
!val, NPU_MMU_DISABLED_POLL_PERIOD_US,
|
||||
ret = readx_poll_timeout(rockchip_iommu_is_enabled, dev, val, !val,
|
||||
NPU_MMU_DISABLED_POLL_PERIOD_US,
|
||||
NPU_MMU_DISABLED_POLL_TIMEOUT_US);
|
||||
if (ret) {
|
||||
dev_err(dev, "iommu still enabled\n");
|
||||
LOG_DEV_ERROR(dev, "iommu still enabled\n");
|
||||
pm_runtime_get_sync(dev);
|
||||
#if KERNEL_VERSION(5, 10, 0) <= LINUX_VERSION_CODE
|
||||
rockchip_monitor_volt_adjust_unlock(rknpu_dev->mdev_info);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
if (rknpu_dev->iommu_en)
|
||||
msleep(20);
|
||||
#endif
|
||||
|
||||
if (rknpu_dev->multiple_domains) {
|
||||
if (rknpu_dev->genpd_dev_npu2)
|
||||
@@ -713,7 +732,11 @@ static int rknpu_power_off(struct rknpu_device *rknpu_dev)
|
||||
pm_runtime_put_sync(rknpu_dev->genpd_dev_npu0);
|
||||
}
|
||||
|
||||
#ifndef FPGA_PLATFORM
|
||||
#if KERNEL_VERSION(5, 10, 0) <= LINUX_VERSION_CODE
|
||||
rockchip_monitor_volt_adjust_unlock(rknpu_dev->mdev_info);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
clk_bulk_disable_unprepare(rknpu_dev->num_clks, rknpu_dev->clks);
|
||||
|
||||
@@ -838,7 +861,8 @@ restore_freq:
|
||||
restore_rm:
|
||||
rockchip_get_read_margin(dev, opp_info, old_supply_vdd->u_volt,
|
||||
&target_rm);
|
||||
rockchip_set_read_margin(dev, opp_info, opp_info->current_rm, is_set_rm);
|
||||
rockchip_set_read_margin(dev, opp_info, opp_info->current_rm,
|
||||
is_set_rm);
|
||||
restore_voltage:
|
||||
regulator_set_voltage(mem_reg, old_supply_mem->u_volt, INT_MAX);
|
||||
regulator_set_voltage(vdd_reg, old_supply_vdd->u_volt, INT_MAX);
|
||||
@@ -864,7 +888,9 @@ static int npu_devfreq_target(struct device *dev, unsigned long *freq,
|
||||
opp_volt = dev_pm_opp_get_voltage(opp);
|
||||
dev_pm_opp_put(opp);
|
||||
|
||||
#if KERNEL_VERSION(5, 10, 0) <= LINUX_VERSION_CODE
|
||||
rockchip_monitor_volt_adjust_lock(rknpu_dev->mdev_info);
|
||||
#endif
|
||||
ret = dev_pm_opp_set_rate(dev, *freq);
|
||||
if (!ret) {
|
||||
rknpu_dev->current_freq = *freq;
|
||||
@@ -873,7 +899,9 @@ static int npu_devfreq_target(struct device *dev, unsigned long *freq,
|
||||
*freq;
|
||||
rknpu_dev->current_volt = opp_volt;
|
||||
}
|
||||
#if KERNEL_VERSION(5, 10, 0) <= LINUX_VERSION_CODE
|
||||
rockchip_monitor_volt_adjust_unlock(rknpu_dev->mdev_info);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1015,7 +1043,8 @@ static int rk3588_npu_set_read_margin(struct device *dev,
|
||||
for (i = 0; i < 3; i++) {
|
||||
ret = regmap_read(opp_info->grf, offset, &val);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to get rm from 0x%x\n", offset);
|
||||
LOG_DEV_ERROR(dev, "failed to get rm from 0x%x\n",
|
||||
offset);
|
||||
return ret;
|
||||
}
|
||||
val &= ~0x1c;
|
||||
@@ -1526,9 +1555,10 @@ static int rknpu_probe(struct platform_device *pdev)
|
||||
}
|
||||
INIT_DEFERRABLE_WORK(&rknpu_dev->power_off_work,
|
||||
rknpu_power_off_delay_work);
|
||||
rknpu_power_off(rknpu_dev);
|
||||
rknpu_dev->is_powered = false;
|
||||
atomic_set(&rknpu_dev->power_refcount, 0);
|
||||
rknpu_power_off(rknpu_dev);
|
||||
atomic_set(&rknpu_dev->cmdline_power_refcount, 0);
|
||||
|
||||
rknpu_debugger_init(rknpu_dev);
|
||||
rknpu_init_timer(rknpu_dev);
|
||||
@@ -1647,7 +1677,7 @@ static struct platform_driver rknpu_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "RKNPU",
|
||||
#ifndef FPGA_PLATFORM
|
||||
#if KERNEL_VERSION(5, 4, 0) < LINUX_VERSION_CODE
|
||||
#if KERNEL_VERSION(5, 5, 0) < LINUX_VERSION_CODE
|
||||
.pm = &rknpu_pm_ops,
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -56,14 +56,13 @@ static int rknpu_gem_get_pages(struct rknpu_gem_object *rknpu_obj)
|
||||
goto free_sgt;
|
||||
}
|
||||
|
||||
dma_sync_sg_for_device(drm->dev, rknpu_obj->sgt->sgl,
|
||||
rknpu_obj->sgt->nents, DMA_TO_DEVICE);
|
||||
|
||||
if (rknpu_obj->flags & RKNPU_MEM_KERNEL_MAPPING) {
|
||||
rknpu_obj->cookie = vmap(rknpu_obj->pages, rknpu_obj->num_pages,
|
||||
VM_MAP, PAGE_KERNEL);
|
||||
if (!rknpu_obj->cookie)
|
||||
if (!rknpu_obj->cookie) {
|
||||
ret = -ENOMEM;
|
||||
goto unmap_sg;
|
||||
}
|
||||
rknpu_obj->kv_addr = rknpu_obj->cookie;
|
||||
}
|
||||
|
||||
@@ -97,8 +96,10 @@ static void rknpu_gem_put_pages(struct rknpu_gem_object *rknpu_obj)
|
||||
{
|
||||
struct drm_device *drm = rknpu_obj->base.dev;
|
||||
|
||||
if (rknpu_obj->flags & RKNPU_MEM_KERNEL_MAPPING)
|
||||
if (rknpu_obj->flags & RKNPU_MEM_KERNEL_MAPPING) {
|
||||
vunmap(rknpu_obj->kv_addr);
|
||||
rknpu_obj->kv_addr = NULL;
|
||||
}
|
||||
|
||||
dma_unmap_sg(drm->dev, rknpu_obj->sgt->sgl, rknpu_obj->sgt->nents,
|
||||
DMA_BIDIRECTIONAL);
|
||||
|
||||
@@ -39,9 +39,23 @@ static int rknpu_core_index(int core_mask)
|
||||
|
||||
static int rknpu_core_mask(int core_index)
|
||||
{
|
||||
int core_mask[3] = { RKNPU_CORE0_MASK, RKNPU_CORE1_MASK,
|
||||
RKNPU_CORE2_MASK };
|
||||
return core_mask[core_index];
|
||||
int core_mask = RKNPU_CORE_AUTO_MASK;
|
||||
|
||||
switch (core_index) {
|
||||
case 0:
|
||||
core_mask = RKNPU_CORE0_MASK;
|
||||
break;
|
||||
case 1:
|
||||
core_mask = RKNPU_CORE1_MASK;
|
||||
break;
|
||||
case 2:
|
||||
core_mask = RKNPU_CORE2_MASK;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return core_mask;
|
||||
}
|
||||
|
||||
static int rknn_get_task_number(struct rknpu_job *job, int core_index)
|
||||
@@ -577,12 +591,9 @@ static void rknpu_job_timeout_clean(struct rknpu_device *rknpu_dev,
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ROCKCHIP_RKNPU_DRM_GEM
|
||||
int rknpu_submit_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
static int rknpu_submit(struct rknpu_device *rknpu_dev,
|
||||
struct rknpu_submit *args)
|
||||
{
|
||||
struct rknpu_device *rknpu_dev = dev_get_drvdata(dev->dev);
|
||||
struct rknpu_submit *args = data;
|
||||
struct rknpu_job *job = NULL;
|
||||
int ret = -EINVAL;
|
||||
|
||||
@@ -676,13 +687,22 @@ int rknpu_submit_ioctl(struct drm_device *dev, void *data,
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ROCKCHIP_RKNPU_DRM_GEM
|
||||
int rknpu_submit_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct rknpu_device *rknpu_dev = dev_get_drvdata(dev->dev);
|
||||
struct rknpu_submit *args = data;
|
||||
|
||||
return rknpu_submit(rknpu_dev, args);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ROCKCHIP_RKNPU_DMA_HEAP
|
||||
int rknpu_submit_ioctl(struct rknpu_device *rknpu_dev, unsigned long data)
|
||||
{
|
||||
struct rknpu_submit args;
|
||||
struct rknpu_job *job = NULL;
|
||||
int ret = -EINVAL;
|
||||
|
||||
if (unlikely(copy_from_user(&args, (struct rknpu_submit *)data,
|
||||
@@ -692,93 +712,7 @@ int rknpu_submit_ioctl(struct rknpu_device *rknpu_dev, unsigned long data)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (args.task_number == 0) {
|
||||
LOG_ERROR("invalid rknpu task number!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
job = rknpu_job_alloc(rknpu_dev, &args);
|
||||
if (!job) {
|
||||
LOG_ERROR("failed to allocate rknpu job!\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (args.flags & RKNPU_JOB_FENCE_IN) {
|
||||
#ifdef CONFIG_ROCKCHIP_RKNPU_FENCE
|
||||
struct dma_fence *in_fence;
|
||||
|
||||
in_fence = sync_file_get_fence(args.fence_fd);
|
||||
|
||||
if (!in_fence) {
|
||||
LOG_ERROR("invalid fence in fd, fd = %d\n",
|
||||
args.fence_fd);
|
||||
return -EINVAL;
|
||||
}
|
||||
args.fence_fd = -1;
|
||||
|
||||
/*
|
||||
* Wait if the fence is from a foreign context, or if the fence
|
||||
* array contains any fence from a foreign context.
|
||||
*/
|
||||
ret = 0;
|
||||
if (!dma_fence_match_context(in_fence,
|
||||
rknpu_dev->fence_ctx->context))
|
||||
ret = dma_fence_wait_timeout(in_fence, true,
|
||||
args.timeout);
|
||||
dma_fence_put(in_fence);
|
||||
if (ret < 0) {
|
||||
if (ret != -ERESTARTSYS)
|
||||
LOG_ERROR("Error (%d) waiting for fence!\n",
|
||||
ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
LOG_ERROR(
|
||||
"failed to use rknpu fence, please enable rknpu fence config!\n");
|
||||
rknpu_job_free(job);
|
||||
return -EINVAL;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (args.flags & RKNPU_JOB_FENCE_OUT) {
|
||||
#ifdef CONFIG_ROCKCHIP_RKNPU_FENCE
|
||||
ret = rknpu_fence_alloc(job);
|
||||
if (ret) {
|
||||
rknpu_job_free(job);
|
||||
return ret;
|
||||
}
|
||||
job->args->fence_fd = rknpu_fence_get_fd(job);
|
||||
args.fence_fd = job->args->fence_fd;
|
||||
#else
|
||||
LOG_ERROR(
|
||||
"failed to use rknpu fence, please enable rknpu fence config!\n");
|
||||
rknpu_job_free(job);
|
||||
return -EINVAL;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (args.flags & RKNPU_JOB_NONBLOCK) {
|
||||
job->flags |= RKNPU_JOB_ASYNC;
|
||||
rknpu_job_timeout_clean(rknpu_dev, job->args->core_mask);
|
||||
rknpu_job_schedule(job);
|
||||
ret = job->ret;
|
||||
if (ret) {
|
||||
rknpu_job_abort(job);
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
rknpu_job_schedule(job);
|
||||
if (args.flags & RKNPU_JOB_PC)
|
||||
job->ret = rknpu_job_wait(job);
|
||||
|
||||
args.task_counter = job->args->task_counter;
|
||||
ret = job->ret;
|
||||
if (!ret)
|
||||
rknpu_job_cleanup(job);
|
||||
else
|
||||
rknpu_job_abort(job);
|
||||
}
|
||||
ret = rknpu_submit(rknpu_dev, &args);
|
||||
|
||||
if (unlikely(copy_to_user((struct rknpu_submit *)data, &args,
|
||||
sizeof(struct rknpu_submit)))) {
|
||||
|
||||
@@ -40,13 +40,13 @@ int rknpu_mem_create_ioctl(struct rknpu_device *rknpu_dev, unsigned long data)
|
||||
if (args.flags & RKNPU_MEM_NON_CONTIGUOUS) {
|
||||
LOG_ERROR("%s: malloc iommu memory unsupported in current!\n",
|
||||
__func__);
|
||||
ret = -EFAULT;
|
||||
ret = -EINVAL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
rknpu_obj = kzalloc(sizeof(*rknpu_obj), GFP_KERNEL);
|
||||
if (!rknpu_obj)
|
||||
return PTR_ERR(rknpu_obj);
|
||||
return -ENOMEM;
|
||||
|
||||
if (args.handle > 0) {
|
||||
fd = args.handle;
|
||||
@@ -64,8 +64,10 @@ int rknpu_mem_create_ioctl(struct rknpu_device *rknpu_dev, unsigned long data)
|
||||
dmabuf = rk_dma_heap_buffer_alloc(rknpu_dev->heap, args.size,
|
||||
O_CLOEXEC | O_RDWR, 0x0,
|
||||
dev_name(rknpu_dev->dev));
|
||||
if (IS_ERR(dmabuf))
|
||||
return PTR_ERR(dmabuf);
|
||||
if (IS_ERR(dmabuf)) {
|
||||
ret = PTR_ERR(dmabuf);
|
||||
goto err_free_obj;
|
||||
}
|
||||
|
||||
rknpu_obj->dmabuf = dmabuf;
|
||||
rknpu_obj->owner = 1;
|
||||
@@ -85,6 +87,7 @@ int rknpu_mem_create_ioctl(struct rknpu_device *rknpu_dev, unsigned long data)
|
||||
|
||||
table = dma_buf_map_attachment(attachment, DMA_BIDIRECTIONAL);
|
||||
if (IS_ERR(table)) {
|
||||
dma_buf_detach(dmabuf, attachment);
|
||||
ret = PTR_ERR(table);
|
||||
goto err_free_dma_buf;
|
||||
}
|
||||
@@ -92,21 +95,26 @@ int rknpu_mem_create_ioctl(struct rknpu_device *rknpu_dev, unsigned long data)
|
||||
for_each_sgtable_sg(table, sgl, i) {
|
||||
phys = sg_dma_address(sgl);
|
||||
page = sg_page(sgl);
|
||||
LOG_DEBUG("%s, %d, phys = %pad, length = 0x%x\n", __func__,
|
||||
__LINE__, &phys, sg_dma_len(sgl));
|
||||
length = sg_dma_len(sgl);
|
||||
LOG_DEBUG("%s, %d, phys = %pad, length = 0x%x\n", __func__,
|
||||
__LINE__, &phys, length);
|
||||
}
|
||||
|
||||
page_count = length >> PAGE_SHIFT;
|
||||
pages = kmalloc_array(page_count, sizeof(struct page), GFP_KERNEL);
|
||||
if (!pages) {
|
||||
ret = -ENOMEM;
|
||||
goto err_detach_dma_buf;
|
||||
}
|
||||
|
||||
for (i = 0; i < page_count; i++)
|
||||
pages[i] = &page[i];
|
||||
|
||||
rknpu_obj->kv_addr = vmap(pages, page_count, VM_MAP, PAGE_KERNEL);
|
||||
kfree(pages);
|
||||
|
||||
dma_buf_unmap_attachment(attachment, table, DMA_BIDIRECTIONAL);
|
||||
dma_buf_detach(dmabuf, attachment);
|
||||
if (!rknpu_obj->kv_addr) {
|
||||
ret = -ENOMEM;
|
||||
goto err_free_pages;
|
||||
}
|
||||
|
||||
rknpu_obj->size = PAGE_ALIGN(args.size);
|
||||
rknpu_obj->dma_addr = phys;
|
||||
@@ -126,18 +134,35 @@ int rknpu_mem_create_ioctl(struct rknpu_device *rknpu_dev, unsigned long data)
|
||||
sizeof(struct rknpu_mem_create)))) {
|
||||
LOG_ERROR("%s: copy_to_user failed\n", __func__);
|
||||
ret = -EFAULT;
|
||||
goto err_free_dma_buf;
|
||||
goto err_unmap_kv_addr;
|
||||
}
|
||||
|
||||
kfree(pages);
|
||||
dma_buf_unmap_attachment(attachment, table, DMA_BIDIRECTIONAL);
|
||||
dma_buf_detach(dmabuf, attachment);
|
||||
|
||||
return 0;
|
||||
|
||||
err_unmap_kv_addr:
|
||||
vunmap(rknpu_obj->kv_addr);
|
||||
rknpu_obj->kv_addr = NULL;
|
||||
|
||||
err_free_pages:
|
||||
kfree(pages);
|
||||
|
||||
err_detach_dma_buf:
|
||||
dma_buf_unmap_attachment(attachment, table, DMA_BIDIRECTIONAL);
|
||||
dma_buf_detach(dmabuf, attachment);
|
||||
|
||||
err_free_dma_buf:
|
||||
dma_buf_put(dmabuf);
|
||||
if (rknpu_obj->owner)
|
||||
rk_dma_heap_buffer_free(dmabuf);
|
||||
return ret;
|
||||
else
|
||||
dma_buf_put(dmabuf);
|
||||
|
||||
err_free_obj:
|
||||
kfree(rknpu_obj);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -156,8 +181,9 @@ int rknpu_mem_destroy_ioctl(struct rknpu_device *rknpu_dev, unsigned long data)
|
||||
}
|
||||
|
||||
if (!kern_addr_valid(args.obj_addr)) {
|
||||
LOG_ERROR("%s: invalid params, unknown obj_addr\n", __func__);
|
||||
ret = -EFAULT;
|
||||
LOG_ERROR("%s: invalid obj_addr: %#llx\n", __func__,
|
||||
(__u64)(uintptr_t)args.obj_addr);
|
||||
ret = -EINVAL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -169,6 +195,12 @@ int rknpu_mem_destroy_ioctl(struct rknpu_device *rknpu_dev, unsigned long data)
|
||||
(__u64)rknpu_obj->dma_addr);
|
||||
|
||||
vunmap(rknpu_obj->kv_addr);
|
||||
rknpu_obj->kv_addr = NULL;
|
||||
|
||||
if (rknpu_obj->owner)
|
||||
rk_dma_heap_buffer_free(dmabuf);
|
||||
else
|
||||
dma_buf_put(dmabuf);
|
||||
|
||||
kfree(rknpu_obj);
|
||||
|
||||
@@ -189,6 +221,13 @@ int rknpu_mem_sync_ioctl(struct rknpu_device *rknpu_dev, unsigned long data)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!kern_addr_valid(args.obj_addr)) {
|
||||
LOG_ERROR("%s: invalid obj_addr: %#llx\n", __func__,
|
||||
(__u64)(uintptr_t)args.obj_addr);
|
||||
ret = -EINVAL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
rknpu_obj = (struct rknpu_mem_object *)(uintptr_t)args.obj_addr;
|
||||
dmabuf = rknpu_obj->dmabuf;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user