On Mon, Mar 26, 2012 at 04:02:55PM +0100, Dave Airlie wrote: <snip> > +int drm_gem_prime_handle_to_fd(struct drm_device *dev, > + struct drm_file *file_priv, uint32_t handle, uint32_t flags, > + int *prime_fd) > +{ > + struct drm_gem_object *obj; > + > + obj = drm_gem_object_lookup(dev, file_priv, handle); > + if (!obj) > + return -ENOENT; > + > + /* don't allow imported buffers to be re-exported */ > + if (obj->import_attach) { > + drm_gem_object_unreference_unlocked(obj); > + return -EINVAL; > + } > + > + if (obj->export_dma_buf) { > + get_file(obj->export_dma_buf->file); > + *prime_fd = dma_buf_fd(obj->export_dma_buf, flags); > + drm_gem_object_unreference_unlocked(obj); > + } else { > + obj->export_dma_buf = > + dev->driver->gem_prime_export(dev, obj, flags); > + if (IS_ERR_OR_NULL(obj->export_dma_buf)) { > + /* normally the created dma-buf takes ownership of the ref, > + * but if that fails then drop the ref > + */ > + drm_gem_object_unreference_unlocked(obj); > + return PTR_ERR(obj->export_dma_buf); PTR_ERR(NULL) seems like a bad idea. Also, you're accessing 'obj' after dropping the reference. > + } > + *prime_fd = dma_buf_fd(obj->export_dma_buf, flags); > + } > + return 0; > +} > +EXPORT_SYMBOL(drm_gem_prime_handle_to_fd); > + > +int drm_gem_prime_fd_to_handle(struct drm_device *dev, > + struct drm_file *file_priv, int prime_fd, uint32_t *handle) > +{ > + struct dma_buf *dma_buf; > + struct drm_gem_object *obj; > + int ret; > + > + dma_buf = dma_buf_get(prime_fd); > + if (IS_ERR(dma_buf)) > + return PTR_ERR(dma_buf); > + > + ret = drm_prime_lookup_fd_handle_mapping(&file_priv->prime, > + dma_buf, handle); > + if (!ret) { > + dma_buf_put(dma_buf); > + return 0; > + } > + > + /* never seen this one, need to import */ > + obj = dev->driver->gem_prime_import(dev, dma_buf); > + if (IS_ERR_OR_NULL(obj)) { > + ret = PTR_ERR(obj); PTR_ERR(NULL) again. > + goto fail_put; > + } > + > + ret = drm_gem_handle_create(file_priv, obj, handle); > + drm_gem_object_unreference_unlocked(obj); > + if (ret) > + goto fail_put; > + > + ret = drm_prime_insert_fd_handle_mapping(&file_priv->prime, > + dma_buf, *handle); > + if (ret) > + goto fail; > + > + return 0; > + > +fail: > + /* hmm, if driver attached, we are relying on the free-object path > + * to detach.. which seems ok.. > + */ > + drm_gem_object_handle_unreference_unlocked(obj); > +fail_put: > + dma_buf_put(dma_buf); > + return ret; > +} > +EXPORT_SYMBOL(drm_gem_prime_fd_to_handle); > + > +int drm_prime_handle_to_fd_ioctl(struct drm_device *dev, void *data, > + struct drm_file *file_priv) > +{ > + struct drm_prime_handle *args = data; > + uint32_t flags; > + > + if (!drm_core_check_feature(dev, DRIVER_PRIME)) > + return -EINVAL; > + > + if (!dev->driver->prime_handle_to_fd) > + return -ENOSYS; > + > + /* we only want to pass DRM_CLOEXEC which is == O_CLOEXEC */ > + flags = args->flags & DRM_CLOEXEC; Check that the unused flags are 0? If you allow broken userspace to pass uninitialized 'flags' to the kernel, you may have compatibility problems if/when you want to add more flags. > + > + return dev->driver->prime_handle_to_fd(dev, file_priv, > + args->handle, flags, &args->fd); > +} > + > +int drm_prime_fd_to_handle_ioctl(struct drm_device *dev, void *data, > + struct drm_file *file_priv) > +{ > + struct drm_prime_handle *args = data; > + > + if (!drm_core_check_feature(dev, DRIVER_PRIME)) > + return -EINVAL; > + > + if (!dev->driver->prime_fd_to_handle) > + return -ENOSYS; > + > + return dev->driver->prime_fd_to_handle(dev, file_priv, > + args->fd, &args->handle); > +} > + > +/* > + * drm_prime_pages_to_sg > + * > + * this helper creates an sg table object from a set of pages > + * the driver is responsible for mapping the pages into the > + * importers address space > + */ > +struct sg_table *drm_prime_pages_to_sg(struct page **pages, int nr_pages) > +{ > + struct sg_table *sg = NULL; > + struct scatterlist *iter; > + int i; > + int ret; > + > + sg = kzalloc(sizeof(struct sg_table), GFP_KERNEL); kmalloc() would be enough. sg_alloc_table() already does a memset(). > + if (!sg) > + goto out; > + > + ret = sg_alloc_table(sg, nr_pages, GFP_KERNEL); > + if (ret) > + goto out; > + > + for_each_sg(sg->sgl, iter, nr_pages, i) > + sg_set_page(iter, pages[i], PAGE_SIZE, 0); > + > + return sg; > +out: > + kfree(sg); > + return NULL; > +} > +EXPORT_SYMBOL(drm_prime_pages_to_sg); -- Ville Syrjälä Intel OTC _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel