feat: update npu-ax3386 with sdk1.2.1
authorHan Gao <gaohan@iscas.ac.cn>
Wed, 18 Oct 2023 14:16:33 +0000 (22:16 +0800)
committerJaehoon Chung <jh80.chung@samsung.com>
Wed, 13 Mar 2024 06:58:49 +0000 (15:58 +0900)
Signed-off-by: Han Gao <gaohan@iscas.ac.cn>
(cherry picked from commit c10fdb081d00a3f37cf73737f4a7f1738bc6b30e)
Signed-off-by: Jaehoon Chung <jh80.chung@samsung.com>
drivers/nna/img_mem/img_mem_anonymous.c
drivers/nna/img_mem/img_mem_dmabuf.c
drivers/nna/img_mem/img_mem_ion.c
drivers/nna/img_mem/img_mem_man.c
drivers/nna/img_mem/img_mem_man_priv.h
drivers/nna/include/img_mem_man.h
drivers/nna/include/uapi/vha.h
drivers/nna/vha/platform/vha_plat_thead.c
drivers/nna/vha/vha_api.c

index eca474b3717085252319498c37972ff42671b902..d2775de1c4773d8c760fe7c1d7359f6dca70ed64 100644 (file)
@@ -65,68 +65,23 @@ struct buffer_data {
 };
 
 static int anonymous_heap_import(struct device *device, struct heap *heap,
-                                               size_t size, enum img_mem_attr attr, uint64_t buf_hnd,
-                                               struct buffer *buffer)
+                                               size_t size, enum img_mem_attr attr, uint64_t buf_fd,
+                                               struct page **pages, struct buffer *buffer)
 {
        struct buffer_data *data;
-       unsigned long cpu_addr = (unsigned long)buf_hnd;
        struct sg_table *sgt;
-       struct page **pages;
        struct scatterlist *sgl;
        int num_pages = (size + PAGE_SIZE - 1) / PAGE_SIZE;
        int ret;
        int i;
 
-       pr_debug("%s:%d buffer %d (0x%p) cpu_addr %#lx for PID:%d\n",
+       pr_debug("%s:%d buffer %d (0x%p) for PID:%d\n",
                        __func__, __LINE__, buffer->id, buffer,
-                       cpu_addr, task_pid_nr(current));
-
-       /* Check alignment */
-       if (cpu_addr & (PAGE_SIZE-1)) {
-               pr_err("%s wrong alignment of %#lx address!\n",
-                               __func__, cpu_addr);
-               return -EFAULT;
-       }
-
-       pages = kmalloc_array(num_pages, sizeof(struct page *),
-                       GFP_KERNEL | __GFP_ZERO);
-       if (!pages) {
-               pr_err("%s failed to allocate memory for pages\n", __func__);
-               return -ENOMEM;
-       }
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 8, 0)
-       down_read(&current->mm->mmap_sem);
-#else
-       down_read(&current->mm->mmap_lock);
-#endif
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)
-       ret = get_user_pages(
-                       cpu_addr, num_pages,
-                       FOLL_WRITE,
-                       pages, NULL);
-#else
-       pr_err("%s get_user_pages not supported for this kernel version\n",
-                               __func__);
-       ret = -1;
-#endif
-#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 8, 0)
-       up_read(&current->mm->mmap_sem);
-#else
-       up_read(&current->mm->mmap_lock);
-#endif
-       if (ret != num_pages) {
-               pr_err("%s failed to get_user_pages count:%d for %#lx address\n",
-                               __func__, num_pages, cpu_addr);
-               ret = -ENOMEM;
-               goto get_user_pages_failed;
-       }
+                       task_pid_nr(current));
 
        sgt = kmalloc(sizeof(struct sg_table), GFP_KERNEL);
-       if (!sgt) {
-               ret = -ENOMEM;
-               goto alloc_sgt_failed;
-       }
+       if (!sgt) 
+               return -ENOMEM;
 
        ret = sg_alloc_table(sgt, num_pages, GFP_KERNEL);
        if (ret) {
@@ -144,6 +99,11 @@ static int anonymous_heap_import(struct device *device, struct heap *heap,
                struct page *page = pages[i];
                sg_set_page(sgl, page, PAGE_SIZE, 0);
 
+               if (trace_physical_pages)
+                       pr_info("%s:%d phys %#llx length %d\n",
+                                __func__, __LINE__,
+                                (unsigned long long)sg_phys(sgl), sgl->length);
+
                /* Sanity check if physical address is
                 * accessible from the device PoV */
                if (~dma_get_mask(device) & sg_phys(sgl)) {
@@ -153,11 +113,6 @@ static int anonymous_heap_import(struct device *device, struct heap *heap,
                        ret = -ERANGE;
                        goto dma_mask_check_failed;
                }
-
-               if (trace_physical_pages)
-                       pr_info("%s:%d phys %#llx length %d\n",
-                                __func__, __LINE__,
-                                (unsigned long long)sg_phys(sgl), sgl->length);
        }
 
        pr_debug("%s:%d buffer %d orig_nents %d\n", __func__, __LINE__,
@@ -174,7 +129,11 @@ static int anonymous_heap_import(struct device *device, struct heap *heap,
                goto dma_mask_check_failed;
        }
 
-       kfree(pages);
+       /* Increase ref count for each page used */
+       for (i = 0; i < num_pages; i++)
+               if (pages[i])
+                       get_page(pages[i]);
+
        return 0;
 
 dma_mask_check_failed:
@@ -183,12 +142,7 @@ alloc_priv_failed:
        sg_free_table(sgt);
 alloc_sgt_pages_failed:
        kfree(sgt);
-get_user_pages_failed:
-       for (i = 0; i < num_pages; i++)
-               if (pages[i])
-                       put_page(pages[i]);
-alloc_sgt_failed:
-       kfree(pages);
+
        return ret;
 }
 
index 8713a4cb5fe7c41e7a96f5a9d343049fd6b944c1..a0e1a5f2d2f22cf66434805fb926740f10fa0029 100644 (file)
@@ -76,23 +76,23 @@ struct buffer_data {
 };
 
 static int dmabuf_heap_import(struct device *device, struct heap *heap,
-                                               size_t size, enum img_mem_attr attr, uint64_t buf_hnd,
-                                               struct buffer *buffer)
+                                               size_t size, enum img_mem_attr attr, uint64_t buf_fd,
+                                               struct page **pages, struct buffer *buffer)
 {
        struct buffer_data *data;
        int ret;
-       int buf_fd = (int)buf_hnd;
+       int dmabuf_fd = (int)buf_fd;
 
-       pr_debug("%s:%d buffer %d (0x%p) buf_fd %d\n", __func__, __LINE__,
-               buffer->id, buffer, buf_fd);
+       pr_debug("%s:%d buffer %d (0x%p) dmabuf_fd %d\n", __func__, __LINE__,
+               buffer->id, buffer, dmabuf_fd);
 
        data = kmalloc(sizeof(struct buffer_data), GFP_KERNEL);
        if (!data)
                return -ENOMEM;
 
-       data->dma_buf = dma_buf_get(buf_fd);
+       data->dma_buf = dma_buf_get(dmabuf_fd);
        if (IS_ERR_OR_NULL(data->dma_buf)) {
-               pr_err("%s dma_buf_get fd %d\n", __func__, buf_fd);
+               pr_err("%s dma_buf_get fd %d\n", __func__, dmabuf_fd);
                ret = -EINVAL;
                goto dma_buf_get_failed;
        }
@@ -101,14 +101,14 @@ static int dmabuf_heap_import(struct device *device, struct heap *heap,
 
        data->attach = dma_buf_attach(data->dma_buf, device);
        if (IS_ERR(data->attach)) {
-               pr_err("%s dma_buf_attach fd %d\n", __func__, buf_fd);
+               pr_err("%s dma_buf_attach fd %d\n", __func__, dmabuf_fd);
                ret = -EINVAL;
                goto dma_buf_attach_failed;
        }
 
        data->sgt = dma_buf_map_attachment(data->attach, DMA_BIDIRECTIONAL);
        if (IS_ERR(data->sgt)) {
-               pr_err("%s dma_buf_map_attachment fd %d\n", __func__, buf_fd);
+               pr_err("%s dma_buf_map_attachment fd %d\n", __func__, dmabuf_fd);
                ret = -EINVAL;
                goto dma_buf_map_failed;
        }
index 632efa8017390a439f4ce7ac8ea610188e10eb6e..e3f8a38c444f6676ecc903283afd0967daa4ab82 100644 (file)
@@ -63,24 +63,24 @@ struct buffer_data {
 };
 
 static int ion_heap_import(struct device *device, struct heap *heap,
-                               size_t size, enum img_mem_attr attr, uint64_t buf_hnd,
-                               struct buffer *buffer)
+                               size_t size, enum img_mem_attr attr, uint64_t buf_fd,
+                               struct page **pages, struct buffer *buffer)
 {
        struct buffer_data *data;
        int ret;
-       int buf_fd = (int)buf_hnd;
+       int ion_buf_fd = (int)buf_fd;
 
-       pr_debug("%s:%d buffer %d (0x%p) buf_fd %d\n", __func__, __LINE__,
-                buffer->id, buffer, buf_fd);
+       pr_debug("%s:%d buffer %d (0x%p) ion_buf_fd %d\n", __func__, __LINE__,
+                buffer->id, buffer, ion_buf_fd);
 
        data = kmalloc(sizeof(struct buffer_data), GFP_KERNEL);
        if (!data)
                return -ENOMEM;
        data->client = heap->priv;
 
-       data->handle = ion_import_dma_buf(data->client, buf_fd);
+       data->handle = ion_import_dma_buf(data->client, ion_buf_fd);
        if (IS_ERR_OR_NULL(data->handle)) {
-               pr_err("%s ion_import_dma_buf fd %d\n", __func__, buf_fd);
+               pr_err("%s ion_import_dma_buf fd %d\n", __func__, ion_buf_fd);
                ret = -EINVAL;
                goto ion_import_dma_buf_failed;
        }
@@ -89,7 +89,7 @@ static int ion_heap_import(struct device *device, struct heap *heap,
 
        data->sgt = ion_sg_table(data->client, data->handle);
        if (IS_ERR(data->sgt)) {
-               pr_err("%s ion_sg_table fd %d\n", __func__, buf_fd);
+               pr_err("%s ion_sg_table fd %d\n", __func__, ion_buf_fd);
                ret = -EINVAL;
                goto ion_sg_table_failed;
        }
index 29ea1b41430450f6ee7184e6be23cb81aacb5dfc..f6b71238e4b80b95dfece6f2fe26ff39968f88dd 100644 (file)
@@ -48,6 +48,7 @@
 #include <linux/slab.h>
 #include <linux/device.h>
 #include <linux/dma-mapping.h>
+#include <linux/delay.h>
 
 #include <img_mem_man.h>
 #include <vha_drv_common.h>
@@ -511,8 +512,8 @@ EXPORT_SYMBOL(img_mem_alloc);
 
 static int _img_mem_import(struct device *device,
                                struct mem_ctx *ctx, struct heap *heap,
-                               size_t size, enum img_mem_attr attr, uint64_t buf_hnd,
-                               struct buffer **buffer_new)
+                               size_t size, enum img_mem_attr attr, uint64_t buf_fd,
+                               struct page **pages, struct buffer **buffer_new)
 {
        struct mem_man *mem_man = &mem_man_data;
        struct buffer *buffer;
@@ -583,7 +584,7 @@ static int _img_mem_import(struct device *device,
        }
 
        ret = heap->ops->import(device, heap, buffer->actual_size, attr,
-                               buf_hnd, buffer);
+                               buf_fd, pages, buffer);
        if (ret) {
                pr_err("%s: heap %d import failed\n", __func__, heap->id);
                goto heap_import_failed;
@@ -608,41 +609,134 @@ idr_alloc_failed:
        return ret;
 }
 
+static void _img_mem_put_pages(size_t size, struct page **pages)
+{
+       int num_pages = (size + PAGE_SIZE - 1) / PAGE_SIZE;
+       int i;
+
+       for (i = 0; i < num_pages; i++)
+               if (pages[i])
+                       put_page(pages[i]);             
+       kfree(pages);
+}
+
+static int _img_mem_get_user_pages(size_t size, uint64_t cpu_ptr,
+                               struct page **pages[])
+{
+       struct page **tmp_pages = NULL;
+       int num_pages = (size + PAGE_SIZE - 1) / PAGE_SIZE;
+       int ret;
+       int cnt = 0;
+
+       /* Check alignment */
+       if (cpu_ptr & (PAGE_SIZE-1)) {
+               pr_err("%s wrong alignment of %#llx address!\n",
+                               __func__, cpu_ptr);
+               return -EFAULT;
+       }
+
+       tmp_pages = kmalloc_array(num_pages, sizeof(struct page *),
+                       GFP_KERNEL | __GFP_ZERO);
+       if (!tmp_pages) {
+               pr_err("%s failed to allocate memory for pages\n", __func__);
+               return -ENOMEM;
+       }
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 8, 0)
+       down_read(&current->mm->mmap_sem);
+#else
+       mmap_read_lock(current->mm);
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)
+       ret = get_user_pages(
+                       cpu_ptr, num_pages,
+                       0,
+                       tmp_pages, NULL);
+#else
+       pr_err("%s get_user_pages not supported for this kernel version\n",
+                                       __func__);
+       ret = -1;
+#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 8, 0)
+       up_read(&current->mm->mmap_sem);
+#else
+       mmap_read_unlock(current->mm);
+#endif
+       if (ret != num_pages) {
+               pr_err("%s failed to get_user_pages count:%d for %#llx address\n",
+                               __func__, num_pages, cpu_ptr);
+               ret = -ENOMEM;
+               goto out_get_user_pages;
+       }
+
+       *pages = tmp_pages;
+
+       return 0;
+
+out_get_user_pages:
+       _img_mem_put_pages(size, tmp_pages);
+
+       return ret;     
+}
+
 int img_mem_import(struct device *device, struct mem_ctx *ctx, int heap_id,
-                       size_t size, enum img_mem_attr attr, uint64_t buf_hnd,
-                       int *buf_id)
+                       size_t size, enum img_mem_attr attr, uint64_t buf_fd,
+                       uint64_t cpu_ptr, int *buf_id)
 {
        struct mem_man *mem_man = &mem_man_data;
        struct heap *heap;
        struct buffer *buffer;
+       struct page **pages = NULL;
        int ret;
 
-       pr_debug("%s heap %d ctx %p hnd %#llx\n", __func__, heap_id, ctx, buf_hnd);
+       pr_debug("%s heap %d ctx %p hnd %#llx\n", __func__, heap_id, ctx, buf_fd);
+
+       if (cpu_ptr) {
+               ret = _img_mem_get_user_pages(size, cpu_ptr, &pages);
+               if (ret) {
+                       pr_err("%s:%d getting user pages failed\n", __func__, __LINE__);
+                       return ret;
+               }
+       }
 
        ret = mutex_lock_interruptible(&mem_man->mutex);
-       if (ret)
-               return ret;
+       if (ret) {
+               pr_err("%s:%d lock interrupted: mem_man->mutex\n", __func__, __LINE__);
+
+               goto lock_interrupted;
+       }
 
        heap = idr_find(&mem_man->heaps, heap_id);
        if (!heap) {
                pr_err("%s: heap id %d not found\n", __func__, heap_id);
-               mutex_unlock(&mem_man->mutex);
-               return -EINVAL;
+               ret = -EINVAL;
+               goto idr_find_failed;
        }
 
-       ret = _img_mem_import(device, ctx, heap, size, attr, buf_hnd, &buffer);
-       if (ret) {
-               mutex_unlock(&mem_man->mutex);
-               return ret;
-       }
+       ret = _img_mem_import(device, ctx, heap, size, attr, buf_fd, pages, &buffer);
+       if (ret)
+               goto mem_import_failed;
 
        *buf_id = buffer->id;
        mutex_unlock(&mem_man->mutex);
 
-       pr_debug("%s buf_hnd %#llx heap %d (%s) buffer %d size %zu\n", __func__,
-               buf_hnd, heap_id, get_heap_name(heap->type), *buf_id, size);
+       if (cpu_ptr)
+               _img_mem_put_pages(size, pages);
+
+       pr_debug("%s buf_fd %#llx heap %d (%s) buffer %d size %zu\n", __func__,
+               buf_fd, heap_id, get_heap_name(heap->type), *buf_id, size);
        pr_debug("%s heap %d ctx %p created buffer %d (%p) size %zu\n",
                __func__, heap_id, ctx, *buf_id, buffer, size);
+
+       return 0;
+
+mem_import_failed:
+idr_find_failed:
+       mutex_unlock(&mem_man->mutex);
+lock_interrupted:
+       if (cpu_ptr)
+               _img_mem_put_pages(size, pages);
+
        return ret;
 }
 EXPORT_SYMBOL(img_mem_import);
@@ -1136,6 +1230,7 @@ uint64_t img_mem_get_single_page(struct mem_ctx *mem_ctx, int buf_id,
                if (ret) {
                        pr_err("%s: heap %d buffer %d no sg_table!\n",
                                                __func__, heap->id, buffer->id);
+                       mutex_unlock(&mem_man->mutex);
                        return -1;
                }
                sgl = sgt->sgl;
@@ -1152,6 +1247,7 @@ uint64_t img_mem_get_single_page(struct mem_ctx *mem_ctx, int buf_id,
                if (!sgl) {
                        pr_err("%s: heap %d buffer %d wrong offset %d!\n",
                                        __func__, heap->id, buffer->id, offset);
+                       mutex_unlock(&mem_man->mutex);
                        return -1;
                }
 
@@ -1168,12 +1264,14 @@ uint64_t img_mem_get_single_page(struct mem_ctx *mem_ctx, int buf_id,
                if (ret) {
                        pr_err("%s: heap %d buffer %d no page array!\n",
                                                __func__, heap->id, buffer->id);
+                       mutex_unlock(&mem_man->mutex);
                        return -1;
                }
 
                if (offset > buffer->actual_size) {
                        pr_err("%s: heap %d buffer %d wrong offset %d!\n",
                                                __func__, heap->id, buffer->id, offset);
+                       mutex_unlock(&mem_man->mutex);
                        return -1;
                }
                addr = addrs[page_idx];
index 072426c6b7164be36f56c2d27bf41057e20ee346..24ac96deaa2ea2dd3a7123b50e549dcc2bdd7055 100644 (file)
@@ -144,8 +144,8 @@ struct heap_ops {
                                 size_t size, enum img_mem_attr attr,
                                 struct buffer *buffer);
        int (*import)(struct device *device, struct heap *heap,
-                                       size_t size, enum img_mem_attr attr, uint64_t buf_hnd,
-                                       struct buffer *buffer);
+                                       size_t size, enum img_mem_attr attr, uint64_t buf_fd,
+                                       struct page **pages, struct buffer *buffer);
        int (*export)(struct device *device, struct heap *heap,
                                        size_t size, enum img_mem_attr attr, struct buffer *buffer,
                                        uint64_t *buf_hnd);
index c4248589820c4091e4a1cd28ade00e3b56f1256f..8da6f6f199b7ae0dbdce2f8406340dea6b3b68d6 100644 (file)
@@ -167,8 +167,8 @@ void img_mem_destroy_proc_ctx(struct mem_ctx *ctx);
 int img_mem_alloc(struct device *device, struct mem_ctx *ctx, int heap_id,
                        size_t size, enum img_mem_attr attributes, int *buf_id);
 int img_mem_import(struct device *device, struct mem_ctx *ctx, int heap_id,
-                        size_t size, enum img_mem_attr attributes, uint64_t buf_hnd,
-                        int *buf_id);
+                        size_t size, enum img_mem_attr attributes, uint64_t buf_fd,
+                        uint64_t cpu_ptr, int *buf_id);
 int img_mem_export(struct device *device, struct mem_ctx *ctx, int buf_id,
                         size_t size, enum img_mem_attr attributes, uint64_t *buf_hnd);
 void img_mem_free(struct mem_ctx *ctx, int buf_id);
index a9d40412359c84000c9990b73d45a6358c5ca2d5..4f3e7f6af021aba3540876975ace49fd1898484d 100644 (file)
@@ -254,8 +254,8 @@ struct vha_alloc_data {
 /* parameters to import a device buffer */
 struct vha_import_data {
        uint64_t size;                          /* [IN] Size of device memory (in bytes)    */
-       uint64_t buf_hnd;                       /* [IN] File descriptor/cpu pointer
-                                                                                                               of buffer to import */
+       uint64_t buf_fd;                        /* [IN] File descriptor */
+       uint64_t cpu_ptr;                       /* [IN] Cpu pointer of buffer to import */
        uint32_t heap_id;                       /* [IN] Heap ID of allocator                */
        uint32_t attributes;    /* [IN] Attributes of buffer                */
        char     name[8];                       /* [IN] short name for buffer               */
index 7aaa9dd2449ac1e8a852ef5a9f146f81796d86ee..91394a18e192bfc75e2c2072e92bfff3b73335bc 100644 (file)
@@ -15,6 +15,8 @@
 #include <linux/platform_device.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
+#include <linux/reset.h>
+#include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/pm.h>
 #include <linux/version.h>
@@ -55,6 +57,10 @@ static struct poll_timer {
 
 } irq_poll_timer;
 
+struct vha_prvdata {
+       struct reset_control *rst;
+};
+
 static ssize_t info_show(struct device_driver *drv, char *buf);
 
 static irqreturn_t dt_plat_thread_irq(int irq, void *dev_id)
@@ -107,6 +113,7 @@ static int vha_plat_probe(struct platform_device *ofdev)
        struct resource res;
        void __iomem *reg_addr;
        uint32_t reg_size, core_size;
+       struct vha_prvdata *data;
        char info[256];
 
        info_show(ofdev->dev.driver, info);
@@ -164,9 +171,22 @@ static int vha_plat_probe(struct platform_device *ofdev)
                goto out_add_dev;
        }
 
+       data = devm_kzalloc(&ofdev->dev, sizeof(*data), GFP_KERNEL);
+       if (!data) {
+               dev_err(&ofdev->dev, "vha private data allocate error\n");
+               ret = -ENOMEM;
+               goto out_add_dev;
+       }
+
+       data->rst = devm_reset_control_get_optional_shared(&ofdev->dev, NULL);
+       if (IS_ERR(data->rst)) {
+               ret = PTR_ERR(data->rst);
+               return ret;
+       }
+
        /* no 'per device' memory heaps used */
        ret = vha_add_dev(&ofdev->dev, NULL, 0,
-                         NULL /* plat priv data */, reg_addr, core_size);
+                         data, reg_addr, core_size);
        if (ret) {
                dev_err(&ofdev->dev, "failed to intialize driver core!\n");
                goto out_add_dev;
index b5d355ee6f4eb0c48ae74b0094bf467c3390531e..d9a835266997b48e0c50ec08e7c7294448123115 100644 (file)
@@ -514,12 +514,12 @@ static long vha_ioctl_import(struct vha_session *session, void __user *buf)
        if (copy_from_user(&data, buf, sizeof(data)))
                return -EFAULT;
 
-       dev_dbg(miscdev->this_device, "%s: session %u, buf_hnd 0x%016llx, size %llu, heap_id %u\n",
-                       __func__, session->id, data.buf_hnd, data.size, data.heap_id);
+       dev_dbg(miscdev->this_device, "%s: session %u, buf_fd 0x%016llx, size %llu, heap_id %u\n",
+                       __func__, session->id, data.buf_fd, data.size, data.heap_id);
 
        ret = img_mem_import(session->vha->dev, session->mem_ctx, data.heap_id,
-                                       (size_t)data.size, data.attributes, data.buf_hnd,
-                                       &data.buf_id);
+                                       (size_t)data.size, data.attributes, data.buf_fd,
+                                       data.cpu_ptr, &data.buf_id);
        if (ret)
                return ret;