Skip to content
This repository was archived by the owner on Nov 8, 2023. It is now read-only.

Commit 1948d28

Browse files
freemangordontomba
authored andcommitted
drm: omapdrm: Support exporting of non-contiguous GEM BOs
Currently code allocates non-scanout BOs from SHMEM and those objects are accessible to userspace by mmap(). However, on devices with no DMM (like OMAP3), the same objects are not accessible by kernel drivers that want to render to them as code refuses to export them. In turn this means that on devices with no DMM, all buffers must be allocated as scanout, otherwise only CPU can access them. On those devices, scanout buffers are allocated from CMA, making those allocations highly unreliable. Fix that by implementing functionality to export SHMEM backed buffers on devices with no DMM. This makes CMA memory only being used when needed, instead for every buffer that has to be off-CPU rendered. Tested on Motorola Droid4 and Nokia N900 Signed-off-by: Ivaylo Dimitrov <[email protected]> Signed-off-by: Tomi Valkeinen <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent 86ad039 commit 1948d28

File tree

3 files changed

+73
-60
lines changed

3 files changed

+73
-60
lines changed

drivers/gpu/drm/omapdrm/omap_gem.c

Lines changed: 70 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ struct omap_gem_object {
3838
/** roll applied when mapping to DMM */
3939
u32 roll;
4040

41-
/** protects dma_addr_cnt, block, pages, dma_addrs and vaddr */
41+
/** protects pin_cnt, block, pages, dma_addrs and vaddr */
4242
struct mutex lock;
4343

4444
/**
@@ -50,24 +50,24 @@ struct omap_gem_object {
5050
* - buffers imported from dmabuf (with the OMAP_BO_MEM_DMABUF flag set)
5151
* if they are physically contiguous (when sgt->orig_nents == 1)
5252
*
53-
* - buffers mapped through the TILER when dma_addr_cnt is not zero, in
54-
* which case the DMA address points to the TILER aperture
53+
* - buffers mapped through the TILER when pin_cnt is not zero, in which
54+
* case the DMA address points to the TILER aperture
5555
*
5656
* Physically contiguous buffers have their DMA address equal to the
5757
* physical address as we don't remap those buffers through the TILER.
5858
*
5959
* Buffers mapped to the TILER have their DMA address pointing to the
60-
* TILER aperture. As TILER mappings are refcounted (through
61-
* dma_addr_cnt) the DMA address must be accessed through omap_gem_pin()
62-
* to ensure that the mapping won't disappear unexpectedly. References
63-
* must be released with omap_gem_unpin().
60+
* TILER aperture. As TILER mappings are refcounted (through pin_cnt)
61+
* the DMA address must be accessed through omap_gem_pin() to ensure
62+
* that the mapping won't disappear unexpectedly. References must be
63+
* released with omap_gem_unpin().
6464
*/
6565
dma_addr_t dma_addr;
6666

6767
/**
68-
* # of users of dma_addr
68+
* # of users
6969
*/
70-
refcount_t dma_addr_cnt;
70+
refcount_t pin_cnt;
7171

7272
/**
7373
* If the buffer has been imported from a dmabuf the OMAP_DB_DMABUF flag
@@ -812,32 +812,28 @@ int omap_gem_pin(struct drm_gem_object *obj, dma_addr_t *dma_addr)
812812

813813
mutex_lock(&omap_obj->lock);
814814

815-
if (!omap_gem_is_contiguous(omap_obj) && priv->has_dmm) {
816-
if (refcount_read(&omap_obj->dma_addr_cnt) == 0) {
815+
if (!omap_gem_is_contiguous(omap_obj)) {
816+
if (refcount_read(&omap_obj->pin_cnt) == 0) {
817817

818-
refcount_set(&omap_obj->dma_addr_cnt, 1);
818+
refcount_set(&omap_obj->pin_cnt, 1);
819819

820820
ret = omap_gem_attach_pages(obj);
821821
if (ret)
822822
goto fail;
823823

824-
ret = omap_gem_pin_tiler(obj);
825-
if (ret)
826-
goto fail;
824+
if (priv->has_dmm) {
825+
ret = omap_gem_pin_tiler(obj);
826+
if (ret)
827+
goto fail;
828+
}
827829
} else {
828-
refcount_inc(&omap_obj->dma_addr_cnt);
830+
refcount_inc(&omap_obj->pin_cnt);
829831
}
830-
831-
if (dma_addr)
832-
*dma_addr = omap_obj->dma_addr;
833-
} else if (omap_gem_is_contiguous(omap_obj)) {
834-
if (dma_addr)
835-
*dma_addr = omap_obj->dma_addr;
836-
} else {
837-
ret = -EINVAL;
838-
goto fail;
839832
}
840833

834+
if (dma_addr)
835+
*dma_addr = omap_obj->dma_addr;
836+
841837
fail:
842838
mutex_unlock(&omap_obj->lock);
843839

@@ -856,27 +852,29 @@ static void omap_gem_unpin_locked(struct drm_gem_object *obj)
856852
struct omap_gem_object *omap_obj = to_omap_bo(obj);
857853
int ret;
858854

859-
if (omap_gem_is_contiguous(omap_obj) || !priv->has_dmm)
855+
if (omap_gem_is_contiguous(omap_obj))
860856
return;
861857

862-
if (refcount_dec_and_test(&omap_obj->dma_addr_cnt)) {
858+
if (refcount_dec_and_test(&omap_obj->pin_cnt)) {
863859
if (omap_obj->sgt) {
864860
sg_free_table(omap_obj->sgt);
865861
kfree(omap_obj->sgt);
866862
omap_obj->sgt = NULL;
867863
}
868-
ret = tiler_unpin(omap_obj->block);
869-
if (ret) {
870-
dev_err(obj->dev->dev,
871-
"could not unpin pages: %d\n", ret);
872-
}
873-
ret = tiler_release(omap_obj->block);
874-
if (ret) {
875-
dev_err(obj->dev->dev,
876-
"could not release unmap: %d\n", ret);
864+
if (priv->has_dmm) {
865+
ret = tiler_unpin(omap_obj->block);
866+
if (ret) {
867+
dev_err(obj->dev->dev,
868+
"could not unpin pages: %d\n", ret);
869+
}
870+
ret = tiler_release(omap_obj->block);
871+
if (ret) {
872+
dev_err(obj->dev->dev,
873+
"could not release unmap: %d\n", ret);
874+
}
875+
omap_obj->dma_addr = 0;
876+
omap_obj->block = NULL;
877877
}
878-
omap_obj->dma_addr = 0;
879-
omap_obj->block = NULL;
880878
}
881879
}
882880

@@ -909,7 +907,7 @@ int omap_gem_rotated_dma_addr(struct drm_gem_object *obj, u32 orient,
909907

910908
mutex_lock(&omap_obj->lock);
911909

912-
if ((refcount_read(&omap_obj->dma_addr_cnt) > 0) && omap_obj->block &&
910+
if ((refcount_read(&omap_obj->pin_cnt) > 0) && omap_obj->block &&
913911
(omap_obj->flags & OMAP_BO_TILED_MASK)) {
914912
*dma_addr = tiler_tsptr(omap_obj->block, orient, x, y);
915913
ret = 0;
@@ -977,7 +975,8 @@ int omap_gem_put_pages(struct drm_gem_object *obj)
977975
return 0;
978976
}
979977

980-
struct sg_table *omap_gem_get_sg(struct drm_gem_object *obj)
978+
struct sg_table *omap_gem_get_sg(struct drm_gem_object *obj,
979+
enum dma_data_direction dir)
981980
{
982981
struct omap_gem_object *omap_obj = to_omap_bo(obj);
983982
dma_addr_t addr;
@@ -1002,28 +1001,44 @@ struct sg_table *omap_gem_get_sg(struct drm_gem_object *obj)
10021001
goto err_unpin;
10031002
}
10041003

1005-
if (omap_obj->flags & OMAP_BO_TILED_MASK) {
1006-
enum tiler_fmt fmt = gem2fmt(omap_obj->flags);
1004+
if (addr) {
1005+
if (omap_obj->flags & OMAP_BO_TILED_MASK) {
1006+
enum tiler_fmt fmt = gem2fmt(omap_obj->flags);
10071007

1008-
len = omap_obj->width << (int)fmt;
1009-
count = omap_obj->height;
1010-
stride = tiler_stride(fmt, 0);
1008+
len = omap_obj->width << (int)fmt;
1009+
count = omap_obj->height;
1010+
stride = tiler_stride(fmt, 0);
1011+
} else {
1012+
len = obj->size;
1013+
count = 1;
1014+
stride = 0;
1015+
}
10111016
} else {
1012-
len = obj->size;
1013-
count = 1;
1014-
stride = 0;
1017+
count = obj->size >> PAGE_SHIFT;
10151018
}
10161019

10171020
ret = sg_alloc_table(sgt, count, GFP_KERNEL);
10181021
if (ret)
10191022
goto err_free;
10201023

1021-
for_each_sg(sgt->sgl, sg, count, i) {
1022-
sg_set_page(sg, phys_to_page(addr), len, offset_in_page(addr));
1023-
sg_dma_address(sg) = addr;
1024-
sg_dma_len(sg) = len;
1024+
/* this must be after omap_gem_pin() to ensure we have pages attached */
1025+
omap_gem_dma_sync_buffer(obj, dir);
1026+
1027+
if (addr) {
1028+
for_each_sg(sgt->sgl, sg, count, i) {
1029+
sg_set_page(sg, phys_to_page(addr), len,
1030+
offset_in_page(addr));
1031+
sg_dma_address(sg) = addr;
1032+
sg_dma_len(sg) = len;
10251033

1026-
addr += stride;
1034+
addr += stride;
1035+
}
1036+
} else {
1037+
for_each_sg(sgt->sgl, sg, count, i) {
1038+
sg_set_page(sg, omap_obj->pages[i], PAGE_SIZE, 0);
1039+
sg_dma_address(sg) = omap_obj->dma_addrs[i];
1040+
sg_dma_len(sg) = PAGE_SIZE;
1041+
}
10271042
}
10281043

10291044
omap_obj->sgt = sgt;
@@ -1133,7 +1148,7 @@ void omap_gem_describe(struct drm_gem_object *obj, struct seq_file *m)
11331148
seq_printf(m, "%08x: %2d (%2d) %08llx %pad (%2d) %p %4d",
11341149
omap_obj->flags, obj->name, kref_read(&obj->refcount),
11351150
off, &omap_obj->dma_addr,
1136-
refcount_read(&omap_obj->dma_addr_cnt),
1151+
refcount_read(&omap_obj->pin_cnt),
11371152
omap_obj->vaddr, omap_obj->roll);
11381153

11391154
if (omap_obj->flags & OMAP_BO_TILED_MASK) {
@@ -1196,7 +1211,7 @@ static void omap_gem_free_object(struct drm_gem_object *obj)
11961211
mutex_lock(&omap_obj->lock);
11971212

11981213
/* The object should not be pinned. */
1199-
WARN_ON(refcount_read(&omap_obj->dma_addr_cnt) > 0);
1214+
WARN_ON(refcount_read(&omap_obj->pin_cnt) > 0);
12001215

12011216
if (omap_obj->pages) {
12021217
if (omap_obj->flags & OMAP_BO_MEM_DMABUF)

drivers/gpu/drm/omapdrm/omap_gem.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,8 @@ u32 omap_gem_flags(struct drm_gem_object *obj);
8282
int omap_gem_rotated_dma_addr(struct drm_gem_object *obj, u32 orient,
8383
int x, int y, dma_addr_t *dma_addr);
8484
int omap_gem_tiled_stride(struct drm_gem_object *obj, u32 orient);
85-
struct sg_table *omap_gem_get_sg(struct drm_gem_object *obj);
85+
struct sg_table *omap_gem_get_sg(struct drm_gem_object *obj,
86+
enum dma_data_direction dir);
8687
void omap_gem_put_sg(struct drm_gem_object *obj, struct sg_table *sgt);
8788

8889
#endif /* __OMAPDRM_GEM_H__ */

drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,10 @@ static struct sg_table *omap_gem_map_dma_buf(
2323
{
2424
struct drm_gem_object *obj = attachment->dmabuf->priv;
2525
struct sg_table *sg;
26-
sg = omap_gem_get_sg(obj);
26+
sg = omap_gem_get_sg(obj, dir);
2727
if (IS_ERR(sg))
2828
return sg;
2929

30-
/* this must be after omap_gem_pin() to ensure we have pages attached */
31-
omap_gem_dma_sync_buffer(obj, dir);
32-
3330
return sg;
3431
}
3532

0 commit comments

Comments
 (0)