video: rockchip: iep: porting for kernel-4.19

Add compile condition of ION and DRM.
Adapt struct kref.
Modify drm's iommu domain get method.
Delete drm's common_iommu_setup_dma_ops.
Delete code about ion.

Change-Id: I340e1798c5930af0a82566f8c40ec93e78084fda
Signed-off-by: Grey Li <grey.li@rock-chips.com>
This commit is contained in:
Grey Li
2019-09-02 16:31:40 +08:00
committed by Tao Huang
parent 7c81bf0ea3
commit 4d9cbff2d4
7 changed files with 44 additions and 324 deletions

View File

@@ -1,2 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_IEP) += hw_iep_reg.o iep_drv.o iep_iommu_drm.o iep_iommu_ion.o iep_iommu_ops.o
iep-y += hw_iep_reg.o iep_drv.o iep_iommu_ops.o
iep-$(CONFIG_DRM) += iep_iommu_drm.o
obj-$(CONFIG_IEP) += iep.o

View File

@@ -80,7 +80,8 @@ struct IEP_CAP {
#define IEP_INFORMATION 1
#if IEP_INFORMATION
#define IEP_INFO(format, args...) printk(format, ## args)
#define IEP_INFO(format, args...) \
printk(KERN_INFO "%s: " format, DRIVER_NAME, ## args)
#else
#define IEP_INFO(format, args...)
#endif

View File

@@ -24,7 +24,6 @@
#include <linux/poll.h>
#include <linux/dma-mapping.h>
#include <linux/fb.h>
#include <linux/rk_fb.h>
#include <linux/wakelock.h>
#include <linux/of.h>
#include <linux/of_platform.h>
@@ -579,8 +578,7 @@ static void iep_service_session_clear(iep_session *session)
static int iep_open(struct inode *inode, struct file *filp)
{
//DECLARE_WAITQUEUE(wait, current);
iep_session *session = (iep_session *)kzalloc(sizeof(iep_session),
GFP_KERNEL);
iep_session *session = kzalloc(sizeof(*session), GFP_KERNEL);
if (NULL == session) {
IEP_ERR("unable to allocate memory for iep_session.\n");
return -ENOMEM;
@@ -660,7 +658,6 @@ static int iep_get_result_sync(iep_session *session)
if (unlikely(ret < 0)) {
IEP_ERR("sync pid %d wait task ret %d\n", session->pid, ret);
iep_del_running_list();
ret = ret;
} else if (0 == ret) {
IEP_ERR("sync pid %d wait %d task done timeout\n",
session->pid, atomic_read(&session->task_running));
@@ -696,8 +693,7 @@ static long iep_ioctl(struct file *filp, uint32_t cmd, unsigned long arg)
case IEP_SET_PARAMETER:
{
struct IEP_MSG *msg;
msg = (struct IEP_MSG *)kzalloc(sizeof(struct IEP_MSG),
GFP_KERNEL);
msg = kzalloc(sizeof(*msg), GFP_KERNEL);
if (msg) {
if (copy_from_user(msg, (struct IEP_MSG *)arg,
sizeof(struct IEP_MSG))) {
@@ -951,8 +947,8 @@ static int iep_drv_probe(struct platform_device *pdev)
struct device *mmu_dev = NULL;
of_property_read_u32(np, "iommu_enabled", &iommu_en);
data = (struct iep_drvdata *)devm_kzalloc(&pdev->dev,
sizeof(struct iep_drvdata), GFP_KERNEL);
data = devm_kzalloc(&pdev->dev, sizeof(*data),
GFP_KERNEL);
if (NULL == data) {
IEP_ERR("failed to allocate driver data.\n");
return -ENOMEM;
@@ -1171,7 +1167,6 @@ static struct platform_driver iep_driver = {
.probe = iep_drv_probe,
.remove = iep_drv_remove,
.driver = {
.owner = THIS_MODULE,
.name = "iep",
#if defined(CONFIG_OF)
.of_match_table = of_match_ptr(iep_dt_ids),
@@ -1284,6 +1279,10 @@ MODULE_LICENSE("GPL");
#ifdef IEP_TEST_CASE
/*this test just test for iep , not test iep's iommu
*so dts need cancel iommus handle
*/
#include "yuv420sp_480x480_interlaced.h"
#include "yuv420sp_480x480_deinterlaced_i2o1.h"
@@ -1293,7 +1292,7 @@ void iep_test_case0(void)
{
struct IEP_MSG msg;
iep_session session;
unsigned int phy_src, phy_dst, phy_tmp;
unsigned int phy_src, phy_tmp;
int i;
int ret = 0;
unsigned char *tmp_buf;
@@ -1313,15 +1312,21 @@ void iep_test_case0(void)
memset(&msg, 0, sizeof(struct IEP_MSG));
memset(tmp_buf, 0xCC, 480 * 480 * 3 / 2);
#ifdef CONFIG_ARM
dmac_flush_range(&yuv420sp_480x480_interlaced[0],
&yuv420sp_480x480_interlaced[480 * 480 * 3 / 2]);
outer_flush_range(virt_to_phys(&yuv420sp_480x480_interlaced[0]),
virt_to_phys(&yuv420sp_480x480_interlaced[480 * 480 * 3 / 2]));
dmac_flush_range(&tmp_buf[0], &tmp_buf[480 * 480 * 3 / 2]);
outer_flush_range(virt_to_phys(&tmp_buf[0]), virt_to_phys(&tmp_buf[480 * 480 * 3 / 2]));
#elif defined(CONFIG_ARM64)
__dma_flush_area(&yuv420sp_480x480_interlaced[0], 480 * 480 * 3 / 2);
__dma_flush_area(&tmp_buf[0], 480 * 480 * 3 / 2);
#endif
phy_src = virt_to_phys(&yuv420sp_480x480_interlaced[0]);
phy_tmp = virt_to_phys(&tmp_buf[0]);
phy_dst = virt_to_phys(&yuv420sp_480x480_deinterlaced_i2o1[0]);
dmac_flush_range(&yuv420sp_480x480_interlaced[0], &yuv420sp_480x480_interlaced[480 * 480 * 3 / 2]);
outer_flush_range(virt_to_phys(&yuv420sp_480x480_interlaced[0]), virt_to_phys(&yuv420sp_480x480_interlaced[480 * 480 * 3 / 2]));
IEP_INFO("*********** IEP MSG GENARATE ************\n");
@@ -1332,8 +1337,8 @@ void iep_test_case0(void)
msg.src.vir_w = 480;
msg.src.vir_h = 480;
msg.src.format = IEP_FORMAT_YCbCr_420_SP;
msg.src.mem_addr = (uint32_t *)phy_src;
msg.src.uv_addr = (uint32_t *)(phy_src + 480 * 480);
msg.src.mem_addr = phy_src;
msg.src.uv_addr = (phy_src + 480 * 480);
msg.src.v_addr = 0;
msg.dst.act_w = 480;
@@ -1343,8 +1348,8 @@ void iep_test_case0(void)
msg.dst.vir_w = 480;
msg.dst.vir_h = 480;
msg.dst.format = IEP_FORMAT_YCbCr_420_SP;
msg.dst.mem_addr = (uint32_t *)phy_tmp;
msg.dst.uv_addr = (uint32_t *)(phy_tmp + 480 * 480);
msg.dst.mem_addr = phy_tmp;
msg.dst.uv_addr = (phy_tmp + 480 * 480);
msg.dst.v_addr = 0;
msg.dein_mode = IEP_DEINTERLACE_MODE_I2O1;
@@ -1361,9 +1366,6 @@ void iep_test_case0(void)
mdelay(10);
dmac_flush_range(&tmp_buf[0], &tmp_buf[480 * 480 * 3 / 2]);
outer_flush_range(virt_to_phys(&tmp_buf[0]), virt_to_phys(&tmp_buf[480 * 480 * 3 / 2]));
IEP_INFO("*********** RESULT CHECKING ************\n");
for (i = 0; i < 480 * 480 * 3 / 2; i++) {

View File

@@ -17,6 +17,7 @@
#include <linux/dma-iommu.h>
#include <linux/dma-buf.h>
#include <linux/dma-mapping.h>
#include <linux/iommu.h>
#include <linux/kref.h>
#include "iep_iommu_ops.h"
@@ -116,12 +117,6 @@ static int iep_drm_attach_unlock(struct iep_iommu_info *iommu_info)
return ret;
}
if (!common_iommu_setup_dma_ops(dev, 0x10000000, SZ_2G, domain->ops)) {
dev_err(dev, "Failed to set dma_ops\n");
iommu_detach_device(domain, dev);
ret = -ENODEV;
}
return ret;
}
@@ -214,7 +209,7 @@ static int iep_drm_free(struct iep_iommu_session_info *session_info,
return -EINVAL;
}
if (atomic_read(&drm_buffer->ref.refcount) == 0) {
if (kref_read(&drm_buffer->ref) == 0) {
dma_buf_put(drm_buffer->dma_buf);
list_del_init(&drm_buffer->list);
kfree(drm_buffer);
@@ -302,7 +297,7 @@ iep_drm_free_fd(struct iep_iommu_session_info *session_info, int fd)
iep_drm_unmap_iommu(session_info, drm_buffer->index);
mutex_lock(&session_info->list_mutex);
if (atomic_read(&drm_buffer->ref.refcount) == 0) {
if (kref_read(&drm_buffer->ref) == 0) {
dma_buf_put(drm_buffer->dma_buf);
list_del_init(&drm_buffer->list);
kfree(drm_buffer);
@@ -426,7 +421,6 @@ fail_out:
static int iep_drm_create(struct iep_iommu_info *iommu_info)
{
struct iep_iommu_drm_info *drm_info;
int ret;
iommu_info->private = kzalloc(sizeof(*drm_info),
GFP_KERNEL);
@@ -434,25 +428,14 @@ static int iep_drm_create(struct iep_iommu_info *iommu_info)
if (!drm_info)
return -ENOMEM;
drm_info->domain = iommu_domain_alloc(&platform_bus_type);
drm_info->domain = iommu_get_domain_for_dev(iommu_info->dev);
drm_info->attached = false;
if (!drm_info->domain) {
kfree(iommu_info->private);
return -ENOMEM;
}
ret = iommu_get_dma_cookie(drm_info->domain);
if (ret)
goto err_free_domain;
iep_drm_attach(iommu_info);
return 0;
err_free_domain:
iommu_domain_free(drm_info->domain);
return ret;
}
static int iep_drm_destroy(struct iep_iommu_info *iommu_info)
@@ -460,8 +443,6 @@ static int iep_drm_destroy(struct iep_iommu_info *iommu_info)
struct iep_iommu_drm_info *drm_info = iommu_info->private;
iep_drm_detach(iommu_info);
iommu_put_dma_cookie(drm_info->domain);
iommu_domain_free(drm_info->domain);
kfree(drm_info);
iommu_info->private = NULL;

View File

@@ -1,259 +0,0 @@
/*
* Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd
* author: Jung Zhao jung.zhao@rock-chips.com
* Randy Li, randy.li@rock-chips.com
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <linux/rockchip_ion.h>
#include <linux/rockchip-iovmm.h>
#include <linux/slab.h>
#include <linux/pm_runtime.h>
#include <linux/memblock.h>
#include <linux/module.h>
#include <linux/of_address.h>
#include <linux/of_graph.h>
#include <linux/component.h>
#include <linux/fence.h>
#include <linux/console.h>
#include <linux/kref.h>
#include <linux/fdtable.h>
#include "iep_iommu_ops.h"
struct iep_ion_buffer {
struct list_head list;
struct ion_handle *handle;
int index;
};
struct iep_iommu_ion_info {
struct ion_client *ion_client;
bool attached;
};
static struct iep_ion_buffer *
iep_ion_get_buffer_no_lock(struct iep_iommu_session_info *session_info,
int idx)
{
struct iep_ion_buffer *ion_buffer = NULL, *n;
list_for_each_entry_safe(ion_buffer, n,
&session_info->buffer_list, list) {
if (ion_buffer->index == idx)
return ion_buffer;
}
return NULL;
}
static void
iep_ion_clear_session(struct iep_iommu_session_info *session_info)
{
/* do nothing */
}
static int iep_ion_attach(struct iep_iommu_info *iommu_info)
{
struct iep_iommu_ion_info *ion_info = iommu_info->private;
int ret;
mutex_lock(&iommu_info->iommu_mutex);
if (ion_info->attached) {
mutex_unlock(&iommu_info->iommu_mutex);
return 0;
}
rockchip_iovmm_activate(iommu_info->dev);
ion_info->attached = true;
mutex_unlock(&iommu_info->iommu_mutex);
return ret;
}
static void iep_ion_detach(struct iep_iommu_info *iommu_info)
{
struct iep_iommu_ion_info *ion_info = iommu_info->private;
mutex_lock(&iommu_info->iommu_mutex);
if (!ion_info->attached) {
mutex_unlock(&iommu_info->iommu_mutex);
return;
}
rockchip_iovmm_deactivate(iommu_info->dev);
ion_info->attached = false;
mutex_unlock(&iommu_info->iommu_mutex);
}
static int iep_ion_destroy(struct iep_iommu_info *iommu_info)
{
struct iep_iommu_ion_info *ion_info = iommu_info->private;
iep_ion_detach(iommu_info);
kfree(ion_info);
iommu_info->private = NULL;
return 0;
}
static int
iep_ion_free(struct iep_iommu_session_info *session_info, int idx)
{
struct iep_ion_buffer *ion_buffer;
mutex_lock(&session_info->list_mutex);
ion_buffer = iep_ion_get_buffer_no_lock(session_info, idx);
if (!ion_buffer) {
mutex_unlock(&session_info->list_mutex);
pr_err("%s can not find %d buffer in list\n", __func__, idx);
return -EINVAL;
}
list_del_init(&ion_buffer->list);
mutex_unlock(&session_info->list_mutex);
kfree(ion_buffer);
return 0;
}
static int
iep_ion_unmap_iommu(struct iep_iommu_session_info *session_info, int idx)
{
struct iep_ion_buffer *ion_buffer;
struct iep_iommu_info *iommu_info = session_info->iommu_info;
struct iep_iommu_ion_info *ion_info = iommu_info->private;
mutex_lock(&session_info->list_mutex);
ion_buffer = iep_ion_get_buffer_no_lock(session_info, idx);
mutex_unlock(&session_info->list_mutex);
if (!ion_buffer) {
pr_err("%s can not find %d buffer in list\n", __func__, idx);
return -EINVAL;
}
ion_free(ion_info->ion_client, ion_buffer->handle);
return 0;
}
static int
iep_ion_map_iommu(struct iep_iommu_session_info *session_info, int idx,
unsigned long *iova, unsigned long *size)
{
struct iep_ion_buffer *ion_buffer;
struct device *dev = session_info->dev;
struct iep_iommu_info *iommu_info = session_info->iommu_info;
struct iep_iommu_ion_info *ion_info = iommu_info->private;
int ret = 0;
/* Force to flush iommu table */
rockchip_iovmm_invalidate_tlb(session_info->dev);
mutex_lock(&session_info->list_mutex);
ion_buffer = iep_ion_get_buffer_no_lock(session_info, idx);
mutex_unlock(&session_info->list_mutex);
if (!ion_buffer) {
pr_err("%s can not find %d buffer in list\n", __func__, idx);
return -EINVAL;
}
if (session_info->mmu_dev)
ret = ion_map_iommu(dev, ion_info->ion_client,
ion_buffer->handle, iova, size);
else
ret = ion_phys(ion_info->ion_client, ion_buffer->handle,
iova, (size_t *)size);
return ret;
}
static int
iep_ion_import(struct iep_iommu_session_info *session_info, int fd)
{
struct iep_ion_buffer *ion_buffer = NULL;
struct iep_iommu_info *iommu_info = session_info->iommu_info;
struct iep_iommu_ion_info *ion_info = iommu_info->private;
ion_buffer = kzalloc(sizeof(*ion_buffer), GFP_KERNEL);
if (!ion_buffer)
return -ENOMEM;
ion_buffer->handle = ion_import_dma_buf(ion_info->ion_client, fd);
INIT_LIST_HEAD(&ion_buffer->list);
mutex_lock(&session_info->list_mutex);
ion_buffer->index = session_info->max_idx;
list_add_tail(&ion_buffer->list, &session_info->buffer_list);
session_info->max_idx++;
if ((session_info->max_idx & 0xfffffff) == 0)
session_info->max_idx = 0;
mutex_unlock(&session_info->list_mutex);
return ion_buffer->index;
}
static int iep_ion_create(struct iep_iommu_info *iommu_info)
{
struct iep_iommu_ion_info *ion_info;
iommu_info->private = kmalloc(sizeof(*ion_info), GFP_KERNEL);
ion_info = iommu_info->private;
if (!ion_info)
return -ENOMEM;
ion_info->ion_client = rockchip_ion_client_create("vpu");
ion_info->attached = false;
iep_ion_attach(iommu_info);
return IS_ERR(ion_info->ion_client) ? -1 : 0;
}
static struct iep_iommu_ops ion_ops = {
.create = iep_ion_create,
.destroy = iep_ion_destroy,
.import = iep_ion_import,
.free = iep_ion_free,
.free_fd = NULL,
.map_iommu = iep_ion_map_iommu,
.unmap_iommu = iep_ion_unmap_iommu,
.dump = NULL,
.attach = iep_ion_attach,
.detach = iep_ion_detach,
.clear = iep_ion_clear_session,
};
/*
* we do not manage the ref number ourselves,
* since ion will help us to do that. what we
* need to do is just map/unmap and import/free
* every time
*/
void iep_iommu_ion_set_ops(struct iep_iommu_info *iommu_info)
{
if (!iommu_info)
return;
iommu_info->ops = &ion_ops;
}

View File

@@ -35,7 +35,7 @@ struct iep_iommu_session_info *iep_iommu_get_session_info
int iep_iommu_create(struct iep_iommu_info *iommu_info)
{
if (!iommu_info || !iommu_info->ops->create)
if (!iommu_info || !iommu_info->ops || !iommu_info->ops->create)
return -EINVAL;
return iommu_info->ops->create(iommu_info);
@@ -46,7 +46,8 @@ int iep_iommu_import(struct iep_iommu_info *iommu_info,
{
struct iep_iommu_session_info *session_info = NULL;
if (!iommu_info || !iommu_info->ops->import || !session)
if (!iommu_info || !iommu_info->ops ||
!iommu_info->ops->import || !session)
return -EINVAL;
session_info = iep_iommu_get_session_info(iommu_info, session);
@@ -84,7 +85,7 @@ int iep_iommu_free(struct iep_iommu_info *iommu_info,
session_info = iep_iommu_get_session_info(iommu_info, session);
if (!iommu_info->ops->free || !session_info)
if (!iommu_info->ops || !iommu_info->ops->free || !session_info)
return -EINVAL;
return iommu_info->ops->free(session_info, idx);
@@ -100,7 +101,7 @@ int iep_iommu_free_fd(struct iep_iommu_info *iommu_info,
session_info = iep_iommu_get_session_info(iommu_info, session);
if (!iommu_info->ops->free_fd || !session_info)
if (!iommu_info->ops || !iommu_info->ops->free_fd || !session_info)
return -EINVAL;
return iommu_info->ops->free_fd(session_info, fd);
@@ -118,7 +119,7 @@ int iep_iommu_map_iommu(struct iep_iommu_info *iommu_info,
session_info = iep_iommu_get_session_info(iommu_info, session);
if (!iommu_info->ops->map_iommu || !session_info)
if (!iommu_info->ops || !iommu_info->ops->map_iommu || !session_info)
return -EINVAL;
return iommu_info->ops->map_iommu(session_info, idx, iova, size);
@@ -134,7 +135,7 @@ int iep_iommu_unmap_iommu(struct iep_iommu_info *iommu_info,
session_info = iep_iommu_get_session_info(iommu_info, session);
if (!iommu_info->ops->unmap_iommu || !session_info)
if (!iommu_info->ops || !iommu_info->ops->unmap_iommu || !session_info)
return -EINVAL;
return iommu_info->ops->unmap_iommu(session_info, idx);
@@ -142,7 +143,7 @@ int iep_iommu_unmap_iommu(struct iep_iommu_info *iommu_info,
int iep_iommu_destroy(struct iep_iommu_info *iommu_info)
{
if (!iommu_info || !iommu_info->ops->destroy)
if (!iommu_info || !iommu_info->ops || !iommu_info->ops->destroy)
return -EINVAL;
return iommu_info->ops->destroy(iommu_info);
@@ -158,7 +159,7 @@ void iep_iommu_dump(struct iep_iommu_info *iommu_info,
session_info = iep_iommu_get_session_info(iommu_info, session);
if (!iommu_info->ops->dump || !session_info)
if (!iommu_info->ops || !iommu_info->ops->dump || !session_info)
return;
iommu_info->ops->dump(session_info);
@@ -174,7 +175,7 @@ void iep_iommu_clear(struct iep_iommu_info *iommu_info,
session_info = iep_iommu_get_session_info(iommu_info, session);
if (!iommu_info->ops->clear || !session_info)
if (!iommu_info->ops || !iommu_info->ops->clear || !session_info)
return;
iommu_info->ops->clear(session_info);
@@ -187,7 +188,7 @@ void iep_iommu_clear(struct iep_iommu_info *iommu_info,
int iep_iommu_attach(struct iep_iommu_info *iommu_info)
{
if (!iommu_info || !iommu_info->ops->attach)
if (!iommu_info || !iommu_info->ops || !iommu_info->ops->attach)
return 0;
return iommu_info->ops->attach(iommu_info);
@@ -195,7 +196,7 @@ int iep_iommu_attach(struct iep_iommu_info *iommu_info)
void iep_iommu_detach(struct iep_iommu_info *iommu_info)
{
if (!iommu_info || !iommu_info->ops->detach)
if (!iommu_info || !iommu_info->ops || !iommu_info->ops->detach)
return;
return iommu_info->ops->detach(iommu_info);
@@ -221,11 +222,6 @@ iep_iommu_info_create(struct device *dev,
case ALLOCATOR_USE_DRM:
iep_iommu_drm_set_ops(iommu_info);
break;
#endif
#ifdef CONFIG_ION
case ALLOCATOR_USE_ION:
iep_iommu_ion_set_ops(iommu_info);
break;
#endif
default:
iommu_info->ops = NULL;

View File

@@ -89,9 +89,6 @@ struct iep_iommu_info {
#ifdef CONFIG_DRM
void iep_iommu_drm_set_ops(struct iep_iommu_info *iommu_info);
#endif
#ifdef CONFIG_ION
void iep_iommu_ion_set_ops(struct iep_iommu_info *iommu_info);
#endif
struct iep_iommu_info *iep_iommu_info_create(struct device *dev,
struct device *mmu_dev,