forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-13 9d77db3c730780c8ef5ccd4b66403ff5675cfe4e
kernel/drivers/gpu/drm/drm_gem_cma_helper.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * drm gem CMA (contiguous memory allocator) helper functions
34 *
....@@ -6,26 +7,18 @@
67 * Based on Samsung Exynos code
78 *
89 * Copyright (c) 2011 Samsung Electronics Co., Ltd.
9
- *
10
- * This program is free software; you can redistribute it and/or
11
- * modify it under the terms of the GNU General Public License
12
- * as published by the Free Software Foundation; either version 2
13
- * of the License, or (at your option) any later version.
14
- * This program is distributed in the hope that it will be useful,
15
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
- * GNU General Public License for more details.
1810 */
1911
20
-#include <linux/mm.h>
21
-#include <linux/slab.h>
22
-#include <linux/mutex.h>
23
-#include <linux/export.h>
2412 #include <linux/dma-buf.h>
2513 #include <linux/dma-mapping.h>
14
+#include <linux/export.h>
15
+#include <linux/mm.h>
16
+#include <linux/mutex.h>
17
+#include <linux/slab.h>
2618
27
-#include <drm/drmP.h>
2819 #include <drm/drm.h>
20
+#include <drm/drm_device.h>
21
+#include <drm/drm_drv.h>
2922 #include <drm/drm_gem_cma_helper.h>
3023 #include <drm/drm_vma_manager.h>
3124
....@@ -112,8 +105,8 @@
112105 cma_obj->vaddr = dma_alloc_wc(drm->dev, size, &cma_obj->paddr,
113106 GFP_KERNEL | __GFP_NOWARN);
114107 if (!cma_obj->vaddr) {
115
- dev_dbg(drm->dev, "failed to allocate buffer with size %zu\n",
116
- size);
108
+ drm_dbg(drm, "failed to allocate buffer with size %zu\n",
109
+ size);
117110 ret = -ENOMEM;
118111 goto error;
119112 }
....@@ -121,7 +114,7 @@
121114 return cma_obj;
122115
123116 error:
124
- drm_gem_object_put_unlocked(&cma_obj->base);
117
+ drm_gem_object_put(&cma_obj->base);
125118 return ERR_PTR(ret);
126119 }
127120 EXPORT_SYMBOL_GPL(drm_gem_cma_create);
....@@ -163,7 +156,7 @@
163156 */
164157 ret = drm_gem_handle_create(file_priv, gem_obj, handle);
165158 /* drop reference from allocate - handle holds it now. */
166
- drm_gem_object_put_unlocked(gem_obj);
159
+ drm_gem_object_put(gem_obj);
167160 if (ret)
168161 return ERR_PTR(ret);
169162
....@@ -176,6 +169,7 @@
176169 *
177170 * This function frees the backing memory of the CMA GEM object, cleans up the
178171 * GEM object state and frees the memory used to store the object itself.
172
+ * If the buffer is imported and the virtual address is set, it is released.
179173 * Drivers using the CMA helpers should set this as their
180174 * &drm_driver.gem_free_object_unlocked callback.
181175 */
....@@ -185,11 +179,13 @@
185179
186180 cma_obj = to_drm_gem_cma_obj(gem_obj);
187181
188
- if (cma_obj->vaddr) {
182
+ if (gem_obj->import_attach) {
183
+ if (cma_obj->vaddr)
184
+ dma_buf_vunmap(gem_obj->import_attach->dmabuf, cma_obj->vaddr);
185
+ drm_prime_gem_destroy(gem_obj, cma_obj->sgt);
186
+ } else if (cma_obj->vaddr) {
189187 dma_free_wc(gem_obj->dev->dev, cma_obj->base.size,
190188 cma_obj->vaddr, cma_obj->paddr);
191
- } else if (gem_obj->import_attach) {
192
- drm_prime_gem_destroy(gem_obj, cma_obj->sgt);
193189 }
194190
195191 drm_gem_object_release(gem_obj);
....@@ -384,13 +380,13 @@
384380 return -EINVAL;
385381
386382 if (!drm_vma_node_is_allowed(node, priv)) {
387
- drm_gem_object_put_unlocked(obj);
383
+ drm_gem_object_put(obj);
388384 return -EACCES;
389385 }
390386
391387 cma_obj = to_drm_gem_cma_obj(obj);
392388
393
- drm_gem_object_put_unlocked(obj);
389
+ drm_gem_object_put(obj);
394390
395391 return cma_obj->vaddr ? (unsigned long)cma_obj->vaddr : -EINVAL;
396392 }
....@@ -436,7 +432,7 @@
436432
437433 sgt = kzalloc(sizeof(*sgt), GFP_KERNEL);
438434 if (!sgt)
439
- return NULL;
435
+ return ERR_PTR(-ENOMEM);
440436
441437 ret = dma_get_sgtable(obj->dev->dev, sgt, cma_obj->vaddr,
442438 cma_obj->paddr, obj->size);
....@@ -447,7 +443,7 @@
447443
448444 out:
449445 kfree(sgt);
450
- return NULL;
446
+ return ERR_PTR(ret);
451447 }
452448 EXPORT_SYMBOL_GPL(drm_gem_cma_prime_get_sg_table);
453449
....@@ -475,26 +471,9 @@
475471 {
476472 struct drm_gem_cma_object *cma_obj;
477473
478
- if (sgt->nents != 1) {
479
- /* check if the entries in the sg_table are contiguous */
480
- dma_addr_t next_addr = sg_dma_address(sgt->sgl);
481
- struct scatterlist *s;
482
- unsigned int i;
483
-
484
- for_each_sg(sgt->sgl, s, sgt->nents, i) {
485
- /*
486
- * sg_dma_address(s) is only valid for entries
487
- * that have sg_dma_len(s) != 0
488
- */
489
- if (!sg_dma_len(s))
490
- continue;
491
-
492
- if (sg_dma_address(s) != next_addr)
493
- return ERR_PTR(-EINVAL);
494
-
495
- next_addr = sg_dma_address(s) + sg_dma_len(s);
496
- }
497
- }
474
+ /* check if the entries in the sg_table are contiguous */
475
+ if (drm_prime_get_contiguous_size(sgt) < attach->dmabuf->size)
476
+ return ERR_PTR(-EINVAL);
498477
499478 /* Create a CMA GEM buffer. */
500479 cma_obj = __drm_gem_cma_create(dev, attach->dmabuf->size);
....@@ -575,3 +554,86 @@
575554 /* Nothing to do */
576555 }
577556 EXPORT_SYMBOL_GPL(drm_gem_cma_prime_vunmap);
557
+
558
+static const struct drm_gem_object_funcs drm_gem_cma_default_funcs = {
559
+ .free = drm_gem_cma_free_object,
560
+ .print_info = drm_gem_cma_print_info,
561
+ .get_sg_table = drm_gem_cma_prime_get_sg_table,
562
+ .vmap = drm_gem_cma_prime_vmap,
563
+ .vm_ops = &drm_gem_cma_vm_ops,
564
+};
565
+
566
+/**
567
+ * drm_gem_cma_create_object_default_funcs - Create a CMA GEM object with a
568
+ * default function table
569
+ * @dev: DRM device
570
+ * @size: Size of the object to allocate
571
+ *
572
+ * This sets the GEM object functions to the default CMA helper functions.
573
+ * This function can be used as the &drm_driver.gem_create_object callback.
574
+ *
575
+ * Returns:
576
+ * A pointer to a allocated GEM object or an error pointer on failure.
577
+ */
578
+struct drm_gem_object *
579
+drm_gem_cma_create_object_default_funcs(struct drm_device *dev, size_t size)
580
+{
581
+ struct drm_gem_cma_object *cma_obj;
582
+
583
+ cma_obj = kzalloc(sizeof(*cma_obj), GFP_KERNEL);
584
+ if (!cma_obj)
585
+ return NULL;
586
+
587
+ cma_obj->base.funcs = &drm_gem_cma_default_funcs;
588
+
589
+ return &cma_obj->base;
590
+}
591
+EXPORT_SYMBOL(drm_gem_cma_create_object_default_funcs);
592
+
593
+/**
594
+ * drm_gem_cma_prime_import_sg_table_vmap - PRIME import another driver's
595
+ * scatter/gather table and get the virtual address of the buffer
596
+ * @dev: DRM device
597
+ * @attach: DMA-BUF attachment
598
+ * @sgt: Scatter/gather table of pinned pages
599
+ *
600
+ * This function imports a scatter/gather table using
601
+ * drm_gem_cma_prime_import_sg_table() and uses dma_buf_vmap() to get the kernel
602
+ * virtual address. This ensures that a CMA GEM object always has its virtual
603
+ * address set. This address is released when the object is freed.
604
+ *
605
+ * This function can be used as the &drm_driver.gem_prime_import_sg_table
606
+ * callback. The &DRM_GEM_CMA_DRIVER_OPS_VMAP macro provides a shortcut to set
607
+ * the necessary DRM driver operations.
608
+ *
609
+ * Returns:
610
+ * A pointer to a newly created GEM object or an ERR_PTR-encoded negative
611
+ * error code on failure.
612
+ */
613
+struct drm_gem_object *
614
+drm_gem_cma_prime_import_sg_table_vmap(struct drm_device *dev,
615
+ struct dma_buf_attachment *attach,
616
+ struct sg_table *sgt)
617
+{
618
+ struct drm_gem_cma_object *cma_obj;
619
+ struct drm_gem_object *obj;
620
+ void *vaddr;
621
+
622
+ vaddr = dma_buf_vmap(attach->dmabuf);
623
+ if (!vaddr) {
624
+ DRM_ERROR("Failed to vmap PRIME buffer\n");
625
+ return ERR_PTR(-ENOMEM);
626
+ }
627
+
628
+ obj = drm_gem_cma_prime_import_sg_table(dev, attach, sgt);
629
+ if (IS_ERR(obj)) {
630
+ dma_buf_vunmap(attach->dmabuf, vaddr);
631
+ return obj;
632
+ }
633
+
634
+ cma_obj = to_drm_gem_cma_obj(obj);
635
+ cma_obj->vaddr = vaddr;
636
+
637
+ return obj;
638
+}
639
+EXPORT_SYMBOL(drm_gem_cma_prime_import_sg_table_vmap);