hc
2024-05-10 cde9070d9970eef1f7ec2360586c802a16230ad8
kernel/drivers/gpu/drm/omapdrm/omap_gem.c
....@@ -1,25 +1,16 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
34 * Author: Rob Clark <rob.clark@linaro.org>
4
- *
5
- * This program is free software; you can redistribute it and/or modify it
6
- * under the terms of the GNU General Public License version 2 as published by
7
- * the Free Software Foundation.
8
- *
9
- * This program is distributed in the hope that it will be useful, but WITHOUT
10
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12
- * more details.
13
- *
14
- * You should have received a copy of the GNU General Public License along with
15
- * this program. If not, see <http://www.gnu.org/licenses/>.
165 */
176
7
+#include <linux/dma-mapping.h>
188 #include <linux/seq_file.h>
199 #include <linux/shmem_fs.h>
2010 #include <linux/spinlock.h>
2111 #include <linux/pfn_t.h>
2212
13
+#include <drm/drm_prime.h>
2314 #include <drm/drm_vma_manager.h>
2415
2516 #include "omap_drv.h"
....@@ -76,7 +67,7 @@
7667 /**
7768 * # of users of dma_addr
7869 */
79
- u32 dma_addr_cnt;
70
+ refcount_t dma_addr_cnt;
8071
8172 /**
8273 * If the buffer has been imported from a dmabuf the OMAP_DB_DMABUF flag
....@@ -205,7 +196,7 @@
205196 struct omap_gem_object *omap_obj = to_omap_bo(obj);
206197 struct omap_drm_private *priv = obj->dev->dev_private;
207198
208
- if (omap_obj->flags & OMAP_BO_TILED) {
199
+ if (omap_obj->flags & OMAP_BO_TILED_MASK) {
209200 enum tiler_fmt fmt = gem2fmt(omap_obj->flags);
210201 int i;
211202
....@@ -333,7 +324,7 @@
333324 struct omap_gem_object *omap_obj = to_omap_bo(obj);
334325 size_t size = obj->size;
335326
336
- if (omap_obj->flags & OMAP_BO_TILED) {
327
+ if (omap_obj->flags & OMAP_BO_TILED_MASK) {
337328 /* for tiled buffers, the virtual size has stride rounded up
338329 * to 4kb.. (to hide the fact that row n+1 might start 16kb or
339330 * 32kb later!). But we don't back the entire buffer with
....@@ -522,7 +513,7 @@
522513 * probably trigger put_pages()?
523514 */
524515
525
- if (omap_obj->flags & OMAP_BO_TILED)
516
+ if (omap_obj->flags & OMAP_BO_TILED_MASK)
526517 ret = omap_gem_fault_2d(obj, vma, vmf);
527518 else
528519 ret = omap_gem_fault_1d(obj, vma, vmf);
....@@ -638,7 +629,7 @@
638629
639630 *offset = omap_gem_mmap_offset(obj);
640631
641
- drm_gem_object_unreference_unlocked(obj);
632
+ drm_gem_object_put(obj);
642633
643634 fail:
644635 return ret;
....@@ -782,18 +773,20 @@
782773 mutex_lock(&omap_obj->lock);
783774
784775 if (!omap_gem_is_contiguous(omap_obj) && priv->has_dmm) {
785
- if (omap_obj->dma_addr_cnt == 0) {
776
+ if (refcount_read(&omap_obj->dma_addr_cnt) == 0) {
786777 u32 npages = obj->size >> PAGE_SHIFT;
787778 enum tiler_fmt fmt = gem2fmt(omap_obj->flags);
788779 struct tiler_block *block;
789780
790781 BUG_ON(omap_obj->block);
791782
783
+ refcount_set(&omap_obj->dma_addr_cnt, 1);
784
+
792785 ret = omap_gem_attach_pages(obj);
793786 if (ret)
794787 goto fail;
795788
796
- if (omap_obj->flags & OMAP_BO_TILED) {
789
+ if (omap_obj->flags & OMAP_BO_TILED_MASK) {
797790 block = tiler_reserve_2d(fmt,
798791 omap_obj->width,
799792 omap_obj->height, 0);
....@@ -822,13 +815,15 @@
822815 omap_obj->block = block;
823816
824817 DBG("got dma address: %pad", &omap_obj->dma_addr);
818
+ } else {
819
+ refcount_inc(&omap_obj->dma_addr_cnt);
825820 }
826821
827
- omap_obj->dma_addr_cnt++;
828
-
829
- *dma_addr = omap_obj->dma_addr;
822
+ if (dma_addr)
823
+ *dma_addr = omap_obj->dma_addr;
830824 } else if (omap_gem_is_contiguous(omap_obj)) {
831
- *dma_addr = omap_obj->dma_addr;
825
+ if (dma_addr)
826
+ *dma_addr = omap_obj->dma_addr;
832827 } else {
833828 ret = -EINVAL;
834829 goto fail;
....@@ -841,38 +836,50 @@
841836 }
842837
843838 /**
839
+ * omap_gem_unpin_locked() - Unpin a GEM object from memory
840
+ * @obj: the GEM object
841
+ *
842
+ * omap_gem_unpin() without locking.
843
+ */
844
+static void omap_gem_unpin_locked(struct drm_gem_object *obj)
845
+{
846
+ struct omap_drm_private *priv = obj->dev->dev_private;
847
+ struct omap_gem_object *omap_obj = to_omap_bo(obj);
848
+ int ret;
849
+
850
+ if (omap_gem_is_contiguous(omap_obj) || !priv->has_dmm)
851
+ return;
852
+
853
+ if (refcount_dec_and_test(&omap_obj->dma_addr_cnt)) {
854
+ ret = tiler_unpin(omap_obj->block);
855
+ if (ret) {
856
+ dev_err(obj->dev->dev,
857
+ "could not unpin pages: %d\n", ret);
858
+ }
859
+ ret = tiler_release(omap_obj->block);
860
+ if (ret) {
861
+ dev_err(obj->dev->dev,
862
+ "could not release unmap: %d\n", ret);
863
+ }
864
+ omap_obj->dma_addr = 0;
865
+ omap_obj->block = NULL;
866
+ }
867
+}
868
+
869
+/**
844870 * omap_gem_unpin() - Unpin a GEM object from memory
845871 * @obj: the GEM object
846872 *
847873 * Unpin the given GEM object previously pinned with omap_gem_pin(). Pins are
848
- * reference-counted, the actualy unpin will only be performed when the number
874
+ * reference-counted, the actual unpin will only be performed when the number
849875 * of calls to this function matches the number of calls to omap_gem_pin().
850876 */
851877 void omap_gem_unpin(struct drm_gem_object *obj)
852878 {
853879 struct omap_gem_object *omap_obj = to_omap_bo(obj);
854
- int ret;
855880
856881 mutex_lock(&omap_obj->lock);
857
-
858
- if (omap_obj->dma_addr_cnt > 0) {
859
- omap_obj->dma_addr_cnt--;
860
- if (omap_obj->dma_addr_cnt == 0) {
861
- ret = tiler_unpin(omap_obj->block);
862
- if (ret) {
863
- dev_err(obj->dev->dev,
864
- "could not unpin pages: %d\n", ret);
865
- }
866
- ret = tiler_release(omap_obj->block);
867
- if (ret) {
868
- dev_err(obj->dev->dev,
869
- "could not release unmap: %d\n", ret);
870
- }
871
- omap_obj->dma_addr = 0;
872
- omap_obj->block = NULL;
873
- }
874
- }
875
-
882
+ omap_gem_unpin_locked(obj);
876883 mutex_unlock(&omap_obj->lock);
877884 }
878885
....@@ -888,8 +895,8 @@
888895
889896 mutex_lock(&omap_obj->lock);
890897
891
- if ((omap_obj->dma_addr_cnt > 0) && omap_obj->block &&
892
- (omap_obj->flags & OMAP_BO_TILED)) {
898
+ if ((refcount_read(&omap_obj->dma_addr_cnt) > 0) && omap_obj->block &&
899
+ (omap_obj->flags & OMAP_BO_TILED_MASK)) {
893900 *dma_addr = tiler_tsptr(omap_obj->block, orient, x, y);
894901 ret = 0;
895902 }
....@@ -904,7 +911,7 @@
904911 {
905912 struct omap_gem_object *omap_obj = to_omap_bo(obj);
906913 int ret = -EINVAL;
907
- if (omap_obj->flags & OMAP_BO_TILED)
914
+ if (omap_obj->flags & OMAP_BO_TILED_MASK)
908915 ret = tiler_stride(gem2fmt(omap_obj->flags), orient);
909916 return ret;
910917 }
....@@ -1039,10 +1046,11 @@
10391046
10401047 seq_printf(m, "%08x: %2d (%2d) %08llx %pad (%2d) %p %4d",
10411048 omap_obj->flags, obj->name, kref_read(&obj->refcount),
1042
- off, &omap_obj->dma_addr, omap_obj->dma_addr_cnt,
1049
+ off, &omap_obj->dma_addr,
1050
+ refcount_read(&omap_obj->dma_addr_cnt),
10431051 omap_obj->vaddr, omap_obj->roll);
10441052
1045
- if (omap_obj->flags & OMAP_BO_TILED) {
1053
+ if (omap_obj->flags & OMAP_BO_TILED_MASK) {
10461054 seq_printf(m, " %dx%d", omap_obj->width, omap_obj->height);
10471055 if (omap_obj->block) {
10481056 struct tcm_area *area = &omap_obj->block->area;
....@@ -1102,7 +1110,7 @@
11021110 mutex_lock(&omap_obj->lock);
11031111
11041112 /* The object should not be pinned. */
1105
- WARN_ON(omap_obj->dma_addr_cnt > 0);
1113
+ WARN_ON(refcount_read(&omap_obj->dma_addr_cnt) > 0);
11061114
11071115 if (omap_obj->pages) {
11081116 if (omap_obj->flags & OMAP_BO_MEM_DMABUF)
....@@ -1129,6 +1137,38 @@
11291137 kfree(omap_obj);
11301138 }
11311139
1140
+static bool omap_gem_validate_flags(struct drm_device *dev, u32 flags)
1141
+{
1142
+ struct omap_drm_private *priv = dev->dev_private;
1143
+
1144
+ switch (flags & OMAP_BO_CACHE_MASK) {
1145
+ case OMAP_BO_CACHED:
1146
+ case OMAP_BO_WC:
1147
+ case OMAP_BO_CACHE_MASK:
1148
+ break;
1149
+
1150
+ default:
1151
+ return false;
1152
+ }
1153
+
1154
+ if (flags & OMAP_BO_TILED_MASK) {
1155
+ if (!priv->usergart)
1156
+ return false;
1157
+
1158
+ switch (flags & OMAP_BO_TILED_MASK) {
1159
+ case OMAP_BO_TILED_8:
1160
+ case OMAP_BO_TILED_16:
1161
+ case OMAP_BO_TILED_32:
1162
+ break;
1163
+
1164
+ default:
1165
+ return false;
1166
+ }
1167
+ }
1168
+
1169
+ return true;
1170
+}
1171
+
11321172 /* GEM buffer object constructor */
11331173 struct drm_gem_object *omap_gem_new(struct drm_device *dev,
11341174 union omap_gem_size gsize, u32 flags)
....@@ -1140,18 +1180,15 @@
11401180 size_t size;
11411181 int ret;
11421182
1143
- /* Validate the flags and compute the memory and cache flags. */
1144
- if (flags & OMAP_BO_TILED) {
1145
- if (!priv->usergart) {
1146
- dev_err(dev->dev, "Tiled buffers require DMM\n");
1147
- return NULL;
1148
- }
1183
+ if (!omap_gem_validate_flags(dev, flags))
1184
+ return NULL;
11491185
1186
+ /* Validate the flags and compute the memory and cache flags. */
1187
+ if (flags & OMAP_BO_TILED_MASK) {
11501188 /*
11511189 * Tiled buffers are always shmem paged backed. When they are
11521190 * scanned out, they are remapped into DMM/TILER.
11531191 */
1154
- flags &= ~OMAP_BO_SCANOUT;
11551192 flags |= OMAP_BO_MEM_SHMEM;
11561193
11571194 /*
....@@ -1162,9 +1199,8 @@
11621199 flags |= tiler_get_cpu_cache_flags();
11631200 } else if ((flags & OMAP_BO_SCANOUT) && !priv->has_dmm) {
11641201 /*
1165
- * OMAP_BO_SCANOUT hints that the buffer doesn't need to be
1166
- * tiled. However, to lower the pressure on memory allocation,
1167
- * use contiguous memory only if no TILER is available.
1202
+ * If we don't have DMM, we must allocate scanout buffers
1203
+ * from contiguous DMA memory.
11681204 */
11691205 flags |= OMAP_BO_MEM_DMA_API;
11701206 } else if (!(flags & OMAP_BO_MEM_DMABUF)) {
....@@ -1183,7 +1219,7 @@
11831219 omap_obj->flags = flags;
11841220 mutex_init(&omap_obj->lock);
11851221
1186
- if (flags & OMAP_BO_TILED) {
1222
+ if (flags & OMAP_BO_TILED_MASK) {
11871223 /*
11881224 * For tiled buffers align dimensions to slot boundaries and
11891225 * calculate size based on aligned dimensions.
....@@ -1261,10 +1297,9 @@
12611297 omap_obj->dma_addr = sg_dma_address(sgt->sgl);
12621298 } else {
12631299 /* Create pages list from sgt */
1264
- struct sg_page_iter iter;
12651300 struct page **pages;
12661301 unsigned int npages;
1267
- unsigned int i = 0;
1302
+ unsigned int ret;
12681303
12691304 npages = DIV_ROUND_UP(size, PAGE_SIZE);
12701305 pages = kcalloc(npages, sizeof(*pages), GFP_KERNEL);
....@@ -1275,14 +1310,9 @@
12751310 }
12761311
12771312 omap_obj->pages = pages;
1278
-
1279
- for_each_sg_page(sgt->sgl, &iter, sgt->orig_nents, 0) {
1280
- pages[i++] = sg_page_iter_page(&iter);
1281
- if (i > npages)
1282
- break;
1283
- }
1284
-
1285
- if (WARN_ON(i != npages)) {
1313
+ ret = drm_prime_sg_to_page_addr_arrays(sgt, pages, NULL,
1314
+ npages);
1315
+ if (ret) {
12861316 omap_gem_free_object(obj);
12871317 obj = ERR_PTR(-ENOMEM);
12881318 goto done;
....@@ -1312,7 +1342,7 @@
13121342 }
13131343
13141344 /* drop reference from allocate - handle holds it now */
1315
- drm_gem_object_unreference_unlocked(obj);
1345
+ drm_gem_object_put(obj);
13161346
13171347 return 0;
13181348 }