Skip to content

Commit 96503f5

Browse files
committed
udl: add prime fd->handle support.
udl can only be used as an output offload so doesn't need to support handle->fd direction. Reviewed-by: Alex Deucher <[email protected]> Signed-off-by: Dave Airlie <[email protected]>
1 parent 0ff926c commit 96503f5

File tree

4 files changed

+92
-1
lines changed

4 files changed

+92
-1
lines changed

drivers/gpu/drm/udl/udl_drv.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ static const struct file_operations udl_driver_fops = {
5757
};
5858

5959
static struct drm_driver driver = {
60-
.driver_features = DRIVER_MODESET | DRIVER_GEM,
60+
.driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME,
6161
.load = udl_driver_load,
6262
.unload = udl_driver_unload,
6363

@@ -70,6 +70,10 @@ static struct drm_driver driver = {
7070
.dumb_map_offset = udl_gem_mmap,
7171
.dumb_destroy = udl_dumb_destroy,
7272
.fops = &udl_driver_fops,
73+
74+
.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
75+
.gem_prime_import = udl_gem_prime_import,
76+
7377
.name = DRIVER_NAME,
7478
.desc = DRIVER_DESC,
7579
.date = DRIVER_DATE,

drivers/gpu/drm/udl/udl_drv.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ struct udl_gem_object {
6666
struct drm_gem_object base;
6767
struct page **pages;
6868
void *vmapping;
69+
struct sg_table *sg;
6970
};
7071

7172
#define to_udl_bo(x) container_of(x, struct udl_gem_object, base)
@@ -118,6 +119,8 @@ int udl_gem_init_object(struct drm_gem_object *obj);
118119
void udl_gem_free_object(struct drm_gem_object *gem_obj);
119120
struct udl_gem_object *udl_gem_alloc_object(struct drm_device *dev,
120121
size_t size);
122+
struct drm_gem_object *udl_gem_prime_import(struct drm_device *dev,
123+
struct dma_buf *dma_buf);
121124

122125
int udl_gem_vmap(struct udl_gem_object *obj);
123126
void udl_gem_vunmap(struct udl_gem_object *obj);

drivers/gpu/drm/udl/udl_fb.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -593,11 +593,20 @@ udl_fb_user_fb_create(struct drm_device *dev,
593593
struct drm_gem_object *obj;
594594
struct udl_framebuffer *ufb;
595595
int ret;
596+
uint32_t size;
596597

597598
obj = drm_gem_object_lookup(dev, file, mode_cmd->handles[0]);
598599
if (obj == NULL)
599600
return ERR_PTR(-ENOENT);
600601

602+
size = mode_cmd->pitches[0] * mode_cmd->height;
603+
size = ALIGN(size, PAGE_SIZE);
604+
605+
if (size > obj->size) {
606+
DRM_ERROR("object size not sufficient for fb %d %zu %d %d\n", size, obj->size, mode_cmd->pitches[0], mode_cmd->height);
607+
return ERR_PTR(-ENOMEM);
608+
}
609+
601610
ufb = kzalloc(sizeof(*ufb), GFP_KERNEL);
602611
if (ufb == NULL)
603612
return ERR_PTR(-ENOMEM);

drivers/gpu/drm/udl/udl_gem.c

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "drmP.h"
1010
#include "udl_drv.h"
1111
#include <linux/shmem_fs.h>
12+
#include <linux/dma-buf.h>
1213

1314
struct udl_gem_object *udl_gem_alloc_object(struct drm_device *dev,
1415
size_t size)
@@ -161,6 +162,12 @@ static void udl_gem_put_pages(struct udl_gem_object *obj)
161162
int page_count = obj->base.size / PAGE_SIZE;
162163
int i;
163164

165+
if (obj->base.import_attach) {
166+
drm_free_large(obj->pages);
167+
obj->pages = NULL;
168+
return;
169+
}
170+
164171
for (i = 0; i < page_count; i++)
165172
page_cache_release(obj->pages[i]);
166173

@@ -195,6 +202,9 @@ void udl_gem_free_object(struct drm_gem_object *gem_obj)
195202
{
196203
struct udl_gem_object *obj = to_udl_bo(gem_obj);
197204

205+
if (gem_obj->import_attach)
206+
drm_prime_gem_destroy(gem_obj, obj->sg);
207+
198208
if (obj->vmapping)
199209
udl_gem_vunmap(obj);
200210

@@ -239,3 +249,68 @@ int udl_gem_mmap(struct drm_file *file, struct drm_device *dev,
239249
mutex_unlock(&dev->struct_mutex);
240250
return ret;
241251
}
252+
253+
static int udl_prime_create(struct drm_device *dev,
254+
size_t size,
255+
struct sg_table *sg,
256+
struct udl_gem_object **obj_p)
257+
{
258+
struct udl_gem_object *obj;
259+
int npages;
260+
int i;
261+
struct scatterlist *iter;
262+
263+
npages = size / PAGE_SIZE;
264+
265+
*obj_p = NULL;
266+
obj = udl_gem_alloc_object(dev, npages * PAGE_SIZE);
267+
if (!obj)
268+
return -ENOMEM;
269+
270+
obj->sg = sg;
271+
obj->pages = drm_malloc_ab(npages, sizeof(struct page *));
272+
if (obj->pages == NULL) {
273+
DRM_ERROR("obj pages is NULL %d\n", npages);
274+
return -ENOMEM;
275+
}
276+
277+
drm_prime_sg_to_page_addr_arrays(sg, obj->pages, NULL, npages);
278+
279+
*obj_p = obj;
280+
return 0;
281+
}
282+
283+
struct drm_gem_object *udl_gem_prime_import(struct drm_device *dev,
284+
struct dma_buf *dma_buf)
285+
{
286+
struct dma_buf_attachment *attach;
287+
struct sg_table *sg;
288+
struct udl_gem_object *uobj;
289+
int ret;
290+
291+
/* need to attach */
292+
attach = dma_buf_attach(dma_buf, dev->dev);
293+
if (IS_ERR(attach))
294+
return ERR_PTR(PTR_ERR(attach));
295+
296+
sg = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
297+
if (IS_ERR(sg)) {
298+
ret = PTR_ERR(sg);
299+
goto fail_detach;
300+
}
301+
302+
ret = udl_prime_create(dev, dma_buf->size, sg, &uobj);
303+
if (ret) {
304+
goto fail_unmap;
305+
}
306+
307+
uobj->base.import_attach = attach;
308+
309+
return &uobj->base;
310+
311+
fail_unmap:
312+
dma_buf_unmap_attachment(attach, sg, DMA_BIDIRECTIONAL);
313+
fail_detach:
314+
dma_buf_detach(dma_buf, attach);
315+
return ERR_PTR(ret);
316+
}

0 commit comments

Comments
 (0)