On Tue, May 22, 2012 at 8:50 AM, Dave Airlie <airlied at gmail.com> wrote: > From: Dave Airlie <airlied at redhat.com> > > This adds prime->fd and fd->prime support to nouveau, > it passes the SG object to TTM, and then populates the > GART entries using it. > > v2: add stubbed kmap + use new function to fill out pages array > for faulting + add reimport test. > > Signed-off-by: Dave Airlie <airlied at redhat.com>
Once again, not familair with nv gart, but the code is pretty much the same as other asics... Reviewed-by: Alex Deucher <alexander.deucher at amd.com> > --- > ?drivers/gpu/drm/nouveau/Makefile ? ? ? ? ?| ? ?2 +- > ?drivers/gpu/drm/nouveau/nouveau_bo.c ? ? ?| ? 42 ++++++-- > ?drivers/gpu/drm/nouveau/nouveau_channel.c | ? ?2 +- > ?drivers/gpu/drm/nouveau/nouveau_drv.c ? ? | ? ?8 ++- > ?drivers/gpu/drm/nouveau/nouveau_drv.h ? ? | ? 10 ++- > ?drivers/gpu/drm/nouveau/nouveau_fence.c ? | ? ?2 +- > ?drivers/gpu/drm/nouveau/nouveau_gem.c ? ? | ? ?6 +- > ?drivers/gpu/drm/nouveau/nouveau_mem.c ? ? | ? ?2 +- > ?drivers/gpu/drm/nouveau/nouveau_prime.c ? | ?163 > +++++++++++++++++++++++++++++ > ?drivers/gpu/drm/nouveau/nouveau_sgdma.c ? | ? ?5 +- > ?drivers/gpu/drm/nouveau/nouveau_vm.c ? ? ?| ? 57 ++++++++++ > ?drivers/gpu/drm/nouveau/nouveau_vm.h ? ? ?| ? ?6 +- > ?drivers/gpu/drm/nouveau/nv04_crtc.c ? ? ? | ? ?2 +- > ?drivers/gpu/drm/nouveau/nv50_crtc.c ? ? ? | ? ?4 +- > ?drivers/gpu/drm/nouveau/nv50_evo.c ? ? ? ?| ? ?4 +- > ?drivers/gpu/drm/nouveau/nvd0_display.c ? ?| ? ?6 +- > ?16 files changed, 296 insertions(+), 25 deletions(-) > ?create mode 100644 drivers/gpu/drm/nouveau/nouveau_prime.c > > diff --git a/drivers/gpu/drm/nouveau/Makefile > b/drivers/gpu/drm/nouveau/Makefile > index 1a2ad7e..01f1335 100644 > --- a/drivers/gpu/drm/nouveau/Makefile > +++ b/drivers/gpu/drm/nouveau/Makefile > @@ -37,7 +37,7 @@ nouveau-y := nouveau_drv.o nouveau_state.o > nouveau_channel.o nouveau_mem.o \ > ? ? ? ? ? ? nv50_calc.o \ > ? ? ? ? ? ? nv04_pm.o nv40_pm.o nv50_pm.o nva3_pm.o nvc0_pm.o \ > ? ? ? ? ? ? nv50_vram.o nvc0_vram.o \ > - ? ? ? ? ? ?nv50_vm.o nvc0_vm.o > + ? ? ? ? ? ?nv50_vm.o nvc0_vm.o nouveau_prime.o > > ?nouveau-$(CONFIG_DRM_NOUVEAU_DEBUG) += nouveau_debugfs.o > ?nouveau-$(CONFIG_COMPAT) += nouveau_ioc32.o > diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c > b/drivers/gpu/drm/nouveau/nouveau_bo.c > index 81599d6..4435e11 100644 > --- a/drivers/gpu/drm/nouveau/nouveau_bo.c > +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c > @@ -89,12 +89,17 @@ nouveau_bo_fixup_align(struct nouveau_bo *nvbo, u32 flags, > ?int > ?nouveau_bo_new(struct drm_device *dev, int size, int align, > ? ? ? ? ? ? ? uint32_t flags, uint32_t tile_mode, uint32_t tile_flags, > + ? ? ? ? ? ? ?struct sg_table *sg, > ? ? ? ? ? ? ? struct nouveau_bo **pnvbo) > ?{ > ? ? ? ?struct drm_nouveau_private *dev_priv = dev->dev_private; > ? ? ? ?struct nouveau_bo *nvbo; > ? ? ? ?size_t acc_size; > ? ? ? ?int ret; > + ? ? ? int type = ttm_bo_type_device; > + > + ? ? ? if (sg) > + ? ? ? ? ? ? ? type = ttm_bo_type_sg; > > ? ? ? ?nvbo = kzalloc(sizeof(struct nouveau_bo), GFP_KERNEL); > ? ? ? ?if (!nvbo) > @@ -120,8 +125,8 @@ nouveau_bo_new(struct drm_device *dev, int size, int > align, > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? sizeof(struct nouveau_bo)); > > ? ? ? ?ret = ttm_bo_init(&dev_priv->ttm.bdev, &nvbo->bo, size, > - ? ? ? ? ? ? ? ? ? ? ? ? ttm_bo_type_device, &nvbo->placement, > - ? ? ? ? ? ? ? ? ? ? ? ? align >> PAGE_SHIFT, 0, false, NULL, acc_size, NULL, > + ? ? ? ? ? ? ? ? ? ? ? ? type, &nvbo->placement, > + ? ? ? ? ? ? ? ? ? ? ? ? align >> PAGE_SHIFT, 0, false, NULL, acc_size, sg, > ? ? ? ? ? ? ? ? ? ? ? ? ?nouveau_bo_del_ttm); > ? ? ? ?if (ret) { > ? ? ? ? ? ? ? ?/* ttm will call nouveau_bo_del_ttm if it fails.. */ > @@ -817,9 +822,14 @@ nouveau_bo_move_ntfy(struct ttm_buffer_object *bo, > struct ttm_mem_reg *new_mem) > ? ? ? ? ? ? ? ?} else > ? ? ? ? ? ? ? ?if (new_mem && new_mem->mem_type == TTM_PL_TT && > ? ? ? ? ? ? ? ? ? ?nvbo->page_shift == vma->vm->spg_shift) { > - ? ? ? ? ? ? ? ? ? ? ? nouveau_vm_map_sg(vma, 0, new_mem-> > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? num_pages << PAGE_SHIFT, > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? new_mem->mm_node); > + ? ? ? ? ? ? ? ? ? ? ? if (((struct nouveau_mem *)new_mem->mm_node)->sg) > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? nouveau_vm_map_sg_table(vma, 0, new_mem-> > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? num_pages << PAGE_SHIFT, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? new_mem->mm_node); > + ? ? ? ? ? ? ? ? ? ? ? else > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? nouveau_vm_map_sg(vma, 0, new_mem-> > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? num_pages << PAGE_SHIFT, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? new_mem->mm_node); > ? ? ? ? ? ? ? ?} else { > ? ? ? ? ? ? ? ? ? ? ? ?nouveau_vm_unmap(vma); > ? ? ? ? ? ? ? ?} > @@ -1058,10 +1068,19 @@ nouveau_ttm_tt_populate(struct ttm_tt *ttm) > ? ? ? ?struct drm_device *dev; > ? ? ? ?unsigned i; > ? ? ? ?int r; > + ? ? ? bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG); > > ? ? ? ?if (ttm->state != tt_unpopulated) > ? ? ? ? ? ? ? ?return 0; > > + ? ? ? if (slave && ttm->sg) { > + ? ? ? ? ? ? ? /* make userspace faulting work */ > + ? ? ? ? ? ? ? drm_prime_sg_to_page_addr_arrays(ttm->sg, ttm->pages, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?ttm_dma->dma_address, > ttm->num_pages); > + ? ? ? ? ? ? ? ttm->state = tt_unbound; > + ? ? ? ? ? ? ? return 0; > + ? ? ? } > + > ? ? ? ?dev_priv = nouveau_bdev(ttm->bdev); > ? ? ? ?dev = dev_priv->dev; > > @@ -1106,6 +1125,10 @@ nouveau_ttm_tt_unpopulate(struct ttm_tt *ttm) > ? ? ? ?struct drm_nouveau_private *dev_priv; > ? ? ? ?struct drm_device *dev; > ? ? ? ?unsigned i; > + ? ? ? bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG); > + > + ? ? ? if (slave) > + ? ? ? ? ? ? ? return; > > ? ? ? ?dev_priv = nouveau_bdev(ttm->bdev); > ? ? ? ?dev = dev_priv->dev; > @@ -1181,9 +1204,12 @@ nouveau_bo_vma_add(struct nouveau_bo *nvbo, struct > nouveau_vm *vm, > > ? ? ? ?if (nvbo->bo.mem.mem_type == TTM_PL_VRAM) > ? ? ? ? ? ? ? ?nouveau_vm_map(vma, nvbo->bo.mem.mm_node); > - ? ? ? else > - ? ? ? if (nvbo->bo.mem.mem_type == TTM_PL_TT) > - ? ? ? ? ? ? ? nouveau_vm_map_sg(vma, 0, size, node); > + ? ? ? else if (nvbo->bo.mem.mem_type == TTM_PL_TT) { > + ? ? ? ? ? ? ? if (node->sg) > + ? ? ? ? ? ? ? ? ? ? ? nouveau_vm_map_sg_table(vma, 0, size, node); > + ? ? ? ? ? ? ? else > + ? ? ? ? ? ? ? ? ? ? ? nouveau_vm_map_sg(vma, 0, size, node); > + ? ? ? } > > ? ? ? ?list_add_tail(&vma->head, &nvbo->vma_list); > ? ? ? ?vma->refcount = 1; > diff --git a/drivers/gpu/drm/nouveau/nouveau_channel.c > b/drivers/gpu/drm/nouveau/nouveau_channel.c > index 846afb0..730bbb2 100644 > --- a/drivers/gpu/drm/nouveau/nouveau_channel.c > +++ b/drivers/gpu/drm/nouveau/nouveau_channel.c > @@ -38,7 +38,7 @@ nouveau_channel_pushbuf_init(struct nouveau_channel *chan) > ? ? ? ?int ret; > > ? ? ? ?/* allocate buffer object */ > - ? ? ? ret = nouveau_bo_new(dev, 65536, 0, mem, 0, 0, &chan->pushbuf_bo); > + ? ? ? ret = nouveau_bo_new(dev, 65536, 0, mem, 0, 0, NULL, > &chan->pushbuf_bo); > ? ? ? ?if (ret) > ? ? ? ? ? ? ? ?goto out; > > diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c > b/drivers/gpu/drm/nouveau/nouveau_drv.c > index 4f2030b..b394ecf 100644 > --- a/drivers/gpu/drm/nouveau/nouveau_drv.c > +++ b/drivers/gpu/drm/nouveau/nouveau_drv.c > @@ -408,7 +408,7 @@ static struct drm_driver driver = { > ? ? ? ?.driver_features = > ? ? ? ? ? ? ? ?DRIVER_USE_AGP | DRIVER_PCI_DMA | DRIVER_SG | > ? ? ? ? ? ? ? ?DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_GEM | > - ? ? ? ? ? ? ? DRIVER_MODESET, > + ? ? ? ? ? ? ? DRIVER_MODESET | DRIVER_PRIME, > ? ? ? ?.load = nouveau_load, > ? ? ? ?.firstopen = nouveau_firstopen, > ? ? ? ?.lastclose = nouveau_lastclose, > @@ -430,6 +430,12 @@ static struct drm_driver driver = { > ? ? ? ?.reclaim_buffers = drm_core_reclaim_buffers, > ? ? ? ?.ioctls = nouveau_ioctls, > ? ? ? ?.fops = &nouveau_driver_fops, > + > + ? ? ? .prime_handle_to_fd = drm_gem_prime_handle_to_fd, > + ? ? ? .prime_fd_to_handle = drm_gem_prime_fd_to_handle, > + ? ? ? .gem_prime_export = nouveau_gem_prime_export, > + ? ? ? .gem_prime_import = nouveau_gem_prime_import, > + > ? ? ? ?.gem_init_object = nouveau_gem_object_new, > ? ? ? ?.gem_free_object = nouveau_gem_object_del, > ? ? ? ?.gem_open_object = nouveau_gem_object_open, > diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h > b/drivers/gpu/drm/nouveau/nouveau_drv.h > index 3aef353..92c9a8a 100644 > --- a/drivers/gpu/drm/nouveau/nouveau_drv.h > +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h > @@ -86,6 +86,7 @@ struct nouveau_mem { > ? ? ? ?u32 memtype; > ? ? ? ?u64 offset; > ? ? ? ?u64 size; > + ? ? ? struct sg_table *sg; > ?}; > > ?struct nouveau_tile_reg { > @@ -1416,7 +1417,9 @@ extern int nv04_crtc_create(struct drm_device *, int > index); > ?extern struct ttm_bo_driver nouveau_bo_driver; > ?extern int nouveau_bo_new(struct drm_device *, int size, int align, > ? ? ? ? ? ? ? ? ? ? ? ? ?uint32_t flags, uint32_t tile_mode, > - ? ? ? ? ? ? ? ? ? ? ? ? uint32_t tile_flags, struct nouveau_bo **); > + ? ? ? ? ? ? ? ? ? ? ? ? uint32_t tile_flags, > + ? ? ? ? ? ? ? ? ? ? ? ? struct sg_table *sg, > + ? ? ? ? ? ? ? ? ? ? ? ? struct nouveau_bo **); > ?extern int nouveau_bo_pin(struct nouveau_bo *, uint32_t flags); > ?extern int nouveau_bo_unpin(struct nouveau_bo *); > ?extern int nouveau_bo_map(struct nouveau_bo *); > @@ -1501,6 +1504,11 @@ extern int nouveau_gem_ioctl_cpu_fini(struct > drm_device *, void *, > ?extern int nouveau_gem_ioctl_info(struct drm_device *, void *, > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?struct drm_file *); > > +extern struct dma_buf *nouveau_gem_prime_export(struct drm_device *dev, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? struct drm_gem_object *obj, int flags); > +extern struct drm_gem_object *nouveau_gem_prime_import(struct drm_device > *dev, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? struct dma_buf *dma_buf); > + > ?/* nouveau_display.c */ > ?int nouveau_display_create(struct drm_device *dev); > ?void nouveau_display_destroy(struct drm_device *dev); > diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c > b/drivers/gpu/drm/nouveau/nouveau_fence.c > index c1dc20f..965e3d2 100644 > --- a/drivers/gpu/drm/nouveau/nouveau_fence.c > +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c > @@ -573,7 +573,7 @@ nouveau_fence_init(struct drm_device *dev) > ? ? ? ?/* Create a shared VRAM heap for cross-channel sync. */ > ? ? ? ?if (USE_SEMA(dev)) { > ? ? ? ? ? ? ? ?ret = nouveau_bo_new(dev, size, 0, TTM_PL_FLAG_VRAM, > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?0, 0, &dev_priv->fence.bo); > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?0, 0, NULL, &dev_priv->fence.bo); > ? ? ? ? ? ? ? ?if (ret) > ? ? ? ? ? ? ? ? ? ? ? ?return ret; > > diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c > b/drivers/gpu/drm/nouveau/nouveau_gem.c > index ed52a6f..666dad0 100644 > --- a/drivers/gpu/drm/nouveau/nouveau_gem.c > +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c > @@ -23,6 +23,7 @@ > ?* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. > ?* > ?*/ > +#include <linux/dma-buf.h> > ?#include "drmP.h" > ?#include "drm.h" > > @@ -53,6 +54,9 @@ nouveau_gem_object_del(struct drm_gem_object *gem) > ? ? ? ? ? ? ? ?nouveau_bo_unpin(nvbo); > ? ? ? ?} > > + ? ? ? if (gem->import_attach) > + ? ? ? ? ? ? ? drm_prime_gem_destroy(gem, nvbo->bo.sg); > + > ? ? ? ?ttm_bo_unref(&bo); > > ? ? ? ?drm_gem_object_release(gem); > @@ -139,7 +143,7 @@ nouveau_gem_new(struct drm_device *dev, int size, int > align, uint32_t domain, > ? ? ? ? ? ? ? ?flags |= TTM_PL_FLAG_SYSTEM; > > ? ? ? ?ret = nouveau_bo_new(dev, size, align, flags, tile_mode, > - ? ? ? ? ? ? ? ? ? ? ? ? ? ?tile_flags, pnvbo); > + ? ? ? ? ? ? ? ? ? ? ? ? ? ?tile_flags, NULL, pnvbo); > ? ? ? ?if (ret) > ? ? ? ? ? ? ? ?return ret; > ? ? ? ?nvbo = *pnvbo; > diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c > b/drivers/gpu/drm/nouveau/nouveau_mem.c > index b08065f..bb2f0a4 100644 > --- a/drivers/gpu/drm/nouveau/nouveau_mem.c > +++ b/drivers/gpu/drm/nouveau/nouveau_mem.c > @@ -416,7 +416,7 @@ nouveau_mem_vram_init(struct drm_device *dev) > > ? ? ? ?if (dev_priv->card_type < NV_50) { > ? ? ? ? ? ? ? ?ret = nouveau_bo_new(dev, 256*1024, 0, TTM_PL_FLAG_VRAM, > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?0, 0, &dev_priv->vga_ram); > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?0, 0, NULL, &dev_priv->vga_ram); > ? ? ? ? ? ? ? ?if (ret == 0) > ? ? ? ? ? ? ? ? ? ? ? ?ret = nouveau_bo_pin(dev_priv->vga_ram, > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? TTM_PL_FLAG_VRAM); > diff --git a/drivers/gpu/drm/nouveau/nouveau_prime.c > b/drivers/gpu/drm/nouveau/nouveau_prime.c > new file mode 100644 > index 0000000..ed6b846 > --- /dev/null > +++ b/drivers/gpu/drm/nouveau/nouveau_prime.c > @@ -0,0 +1,163 @@ > + > +#include "drmP.h" > +#include "drm.h" > + > +#include "nouveau_drv.h" > +#include "nouveau_drm.h" > +#include "nouveau_dma.h" > + > +#include <linux/dma-buf.h> > + > +static struct sg_table *nouveau_gem_map_dma_buf(struct dma_buf_attachment > *attachment, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? enum dma_data_direction dir) > +{ > + ? ? ? struct nouveau_bo *nvbo = attachment->dmabuf->priv; > + ? ? ? struct drm_device *dev = nvbo->gem->dev; > + ? ? ? int npages = nvbo->bo.num_pages; > + ? ? ? struct sg_table *sg; > + ? ? ? int nents; > + > + ? ? ? mutex_lock(&dev->struct_mutex); > + ? ? ? sg = drm_prime_pages_to_sg(nvbo->bo.ttm->pages, npages); > + ? ? ? nents = dma_map_sg(attachment->dev, sg->sgl, sg->nents, dir); > + ? ? ? mutex_unlock(&dev->struct_mutex); > + ? ? ? return sg; > +} > + > +static void nouveau_gem_unmap_dma_buf(struct dma_buf_attachment *attachment, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? struct sg_table *sg, enum > dma_data_direction dir) > +{ > + ? ? ? dma_unmap_sg(attachment->dev, sg->sgl, sg->nents, dir); > + ? ? ? sg_free_table(sg); > + ? ? ? kfree(sg); > +} > + > +static void nouveau_gem_dmabuf_release(struct dma_buf *dma_buf) > +{ > + ? ? ? struct nouveau_bo *nvbo = dma_buf->priv; > + > + ? ? ? if (nvbo->gem->export_dma_buf == dma_buf) { > + ? ? ? ? ? ? ? nvbo->gem->export_dma_buf = NULL; > + ? ? ? ? ? ? ? drm_gem_object_unreference_unlocked(nvbo->gem); > + ? ? ? } > +} > + > +static void *nouveau_gem_kmap_atomic(struct dma_buf *dma_buf, unsigned long > page_num) > +{ > + ? ? ? return NULL; > +} > + > +static void nouveau_gem_kunmap_atomic(struct dma_buf *dma_buf, unsigned long > page_num, void *addr) > +{ > + > +} > +static void *nouveau_gem_kmap(struct dma_buf *dma_buf, unsigned long > page_num) > +{ > + ? ? ? return NULL; > +} > + > +static void nouveau_gem_kunmap(struct dma_buf *dma_buf, unsigned long > page_num, void *addr) > +{ > + > +} > + > +struct dma_buf_ops nouveau_dmabuf_ops = ?{ > + ? ? ? .map_dma_buf = nouveau_gem_map_dma_buf, > + ? ? ? .unmap_dma_buf = nouveau_gem_unmap_dma_buf, > + ? ? ? .release = nouveau_gem_dmabuf_release, > + ? ? ? .kmap = nouveau_gem_kmap, > + ? ? ? .kmap_atomic = nouveau_gem_kmap_atomic, > + ? ? ? .kunmap = nouveau_gem_kunmap, > + ? ? ? .kunmap_atomic = nouveau_gem_kunmap_atomic, > +}; > + > +static int > +nouveau_prime_new(struct drm_device *dev, > + ? ? ? ? ? ? ? ? size_t size, > + ? ? ? ? ? ? ? ? struct sg_table *sg, > + ? ? ? ? ? ? ? ? struct nouveau_bo **pnvbo) > +{ > + ? ? ? struct nouveau_bo *nvbo; > + ? ? ? u32 flags = 0; > + ? ? ? int ret; > + > + ? ? ? flags = TTM_PL_FLAG_TT; > + > + ? ? ? ret = nouveau_bo_new(dev, size, 0, flags, 0, 0, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ?sg, pnvbo); > + ? ? ? if (ret) > + ? ? ? ? ? ? ? return ret; > + ? ? ? nvbo = *pnvbo; > + > + ? ? ? /* we restrict allowed domains on nv50+ to only the types > + ? ? ? ?* that were requested at creation time. ?not possibly on > + ? ? ? ?* earlier chips without busting the ABI. > + ? ? ? ?*/ > + ? ? ? nvbo->valid_domains = NOUVEAU_GEM_DOMAIN_GART; > + ? ? ? nvbo->gem = drm_gem_object_alloc(dev, nvbo->bo.mem.size); > + ? ? ? if (!nvbo->gem) { > + ? ? ? ? ? ? ? nouveau_bo_ref(NULL, pnvbo); > + ? ? ? ? ? ? ? return -ENOMEM; > + ? ? ? } > + > + ? ? ? nvbo->gem->driver_private = nvbo; > + ? ? ? return 0; > +} > + > +struct dma_buf *nouveau_gem_prime_export(struct drm_device *dev, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? struct drm_gem_object *obj, int flags) > +{ > + ? ? ? struct nouveau_bo *nvbo = nouveau_gem_object(obj); > + ? ? ? int ret = 0; > + > + ? ? ? /* pin buffer into GTT */ > + ? ? ? ret = nouveau_bo_pin(nvbo, TTM_PL_FLAG_TT); > + ? ? ? if (ret) > + ? ? ? ? ? ? ? return ERR_PTR(-EINVAL); > + > + ? ? ? return dma_buf_export(nvbo, &nouveau_dmabuf_ops, obj->size, flags); > +} > + > +struct drm_gem_object *nouveau_gem_prime_import(struct drm_device *dev, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? struct dma_buf *dma_buf) > +{ > + ? ? ? struct dma_buf_attachment *attach; > + ? ? ? struct sg_table *sg; > + ? ? ? struct nouveau_bo *nvbo; > + ? ? ? int ret; > + > + ? ? ? if (dma_buf->ops == &nouveau_dmabuf_ops) { > + ? ? ? ? ? ? ? nvbo = dma_buf->priv; > + ? ? ? ? ? ? ? if (nvbo->gem) { > + ? ? ? ? ? ? ? ? ? ? ? if (nvbo->gem->dev == dev) { > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? drm_gem_object_reference(nvbo->gem); > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? return nvbo->gem; > + ? ? ? ? ? ? ? ? ? ? ? } > + ? ? ? ? ? ? ? } > + ? ? ? } > + ? ? ? /* need to attach */ > + ? ? ? attach = dma_buf_attach(dma_buf, dev->dev); > + ? ? ? if (IS_ERR(attach)) > + ? ? ? ? ? ? ? return ERR_PTR(PTR_ERR(attach)); > + > + ? ? ? sg = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL); > + ? ? ? if (IS_ERR(sg)) { > + ? ? ? ? ? ? ? ret = PTR_ERR(sg); > + ? ? ? ? ? ? ? goto fail_detach; > + ? ? ? } > + > + ? ? ? ret = nouveau_prime_new(dev, dma_buf->size, sg, &nvbo); > + ? ? ? if (ret) > + ? ? ? ? ? ? ? goto fail_unmap; > + > + ? ? ? nvbo->gem->import_attach = attach; > + > + ? ? ? return nvbo->gem; > + > +fail_unmap: > + ? ? ? dma_buf_unmap_attachment(attach, sg, DMA_BIDIRECTIONAL); > +fail_detach: > + ? ? ? dma_buf_detach(dma_buf, attach); > + ? ? ? return ERR_PTR(ret); > +} > + > diff --git a/drivers/gpu/drm/nouveau/nouveau_sgdma.c > b/drivers/gpu/drm/nouveau/nouveau_sgdma.c > index 47f245e..27aac9a 100644 > --- a/drivers/gpu/drm/nouveau/nouveau_sgdma.c > +++ b/drivers/gpu/drm/nouveau/nouveau_sgdma.c > @@ -290,7 +290,10 @@ nv50_sgdma_bind(struct ttm_tt *ttm, struct ttm_mem_reg > *mem) > ? ? ? ?struct nouveau_mem *node = mem->mm_node; > > ? ? ? ?/* noop: bound in move_notify() */ > - ? ? ? node->pages = nvbe->ttm.dma_address; > + ? ? ? if (ttm->sg) { > + ? ? ? ? ? ? ? node->sg = ttm->sg; > + ? ? ? } else > + ? ? ? ? ? ? ? node->pages = nvbe->ttm.dma_address; > ? ? ? ?return 0; > ?} > > diff --git a/drivers/gpu/drm/nouveau/nouveau_vm.c > b/drivers/gpu/drm/nouveau/nouveau_vm.c > index 2bf6c03..11edd5e 100644 > --- a/drivers/gpu/drm/nouveau/nouveau_vm.c > +++ b/drivers/gpu/drm/nouveau/nouveau_vm.c > @@ -77,6 +77,63 @@ nouveau_vm_map(struct nouveau_vma *vma, struct nouveau_mem > *node) > ?} > > ?void > +nouveau_vm_map_sg_table(struct nouveau_vma *vma, u64 delta, u64 length, > + ? ? ? ? ? ? ? ? ? ? ? struct nouveau_mem *mem) > +{ > + ? ? ? struct nouveau_vm *vm = vma->vm; > + ? ? ? int big = vma->node->type != vm->spg_shift; > + ? ? ? u32 offset = vma->node->offset + (delta >> 12); > + ? ? ? u32 bits = vma->node->type - 12; > + ? ? ? u32 num ?= length >> vma->node->type; > + ? ? ? u32 pde ?= (offset >> vm->pgt_bits) - vm->fpde; > + ? ? ? u32 pte ?= (offset & ((1 << vm->pgt_bits) - 1)) >> bits; > + ? ? ? u32 max ?= 1 << (vm->pgt_bits - bits); > + ? ? ? unsigned m, sglen; > + ? ? ? u32 end, len; > + ? ? ? int i; > + ? ? ? struct scatterlist *sg; > + > + ? ? ? for_each_sg(mem->sg->sgl, sg, mem->sg->nents, i) { > + ? ? ? ? ? ? ? struct nouveau_gpuobj *pgt = vm->pgt[pde].obj[big]; > + ? ? ? ? ? ? ? sglen = sg_dma_len(sg) >> PAGE_SHIFT; > + > + ? ? ? ? ? ? ? end = pte + sglen; > + ? ? ? ? ? ? ? if (unlikely(end >= max)) > + ? ? ? ? ? ? ? ? ? ? ? end = max; > + ? ? ? ? ? ? ? len = end - pte; > + > + ? ? ? ? ? ? ? for (m = 0; m < len; m++) { > + ? ? ? ? ? ? ? ? ? ? ? dma_addr_t addr = sg_dma_address(sg) + (m << > PAGE_SHIFT); > + > + ? ? ? ? ? ? ? ? ? ? ? vm->map_sg(vma, pgt, mem, pte, 1, &addr); > + ? ? ? ? ? ? ? ? ? ? ? num--; > + ? ? ? ? ? ? ? ? ? ? ? pte++; > + > + ? ? ? ? ? ? ? ? ? ? ? if (num == 0) > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? goto finish; > + ? ? ? ? ? ? ? } > + ? ? ? ? ? ? ? if (unlikely(end >= max)) { > + ? ? ? ? ? ? ? ? ? ? ? pde++; > + ? ? ? ? ? ? ? ? ? ? ? pte = 0; > + ? ? ? ? ? ? ? } > + ? ? ? ? ? ? ? if (m < sglen) { > + ? ? ? ? ? ? ? ? ? ? ? for (; m < sglen; m++) { > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? dma_addr_t addr = sg_dma_address(sg) + (m << > PAGE_SHIFT); > + > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? vm->map_sg(vma, pgt, mem, pte, 1, &addr); > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? num--; > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? pte++; > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? if (num == 0) > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? goto finish; > + ? ? ? ? ? ? ? ? ? ? ? } > + ? ? ? ? ? ? ? } > + > + ? ? ? } > +finish: > + ? ? ? vm->flush(vm); > +} > + > +void > ?nouveau_vm_map_sg(struct nouveau_vma *vma, u64 delta, u64 length, > ? ? ? ? ? ? ? ? ?struct nouveau_mem *mem) > ?{ > diff --git a/drivers/gpu/drm/nouveau/nouveau_vm.h > b/drivers/gpu/drm/nouveau/nouveau_vm.h > index 4fb6e72..a8246e7 100644 > --- a/drivers/gpu/drm/nouveau/nouveau_vm.h > +++ b/drivers/gpu/drm/nouveau/nouveau_vm.h > @@ -72,6 +72,9 @@ struct nouveau_vm { > ? ? ? ? ? ? ? ? ? ?u64 phys, u64 delta); > ? ? ? ?void (*map_sg)(struct nouveau_vma *, struct nouveau_gpuobj *, > ? ? ? ? ? ? ? ? ? ? ? struct nouveau_mem *, u32 pte, u32 cnt, dma_addr_t *); > + > + ? ? ? void (*map_sg_table)(struct nouveau_vma *, struct nouveau_gpuobj *, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ?struct nouveau_mem *, u32 pte, u32 cnt, > dma_addr_t *); > ? ? ? ?void (*unmap)(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt); > ? ? ? ?void (*flush)(struct nouveau_vm *); > ?}; > @@ -90,7 +93,8 @@ void nouveau_vm_unmap(struct nouveau_vma *); > ?void nouveau_vm_unmap_at(struct nouveau_vma *, u64 offset, u64 length); > ?void nouveau_vm_map_sg(struct nouveau_vma *, u64 offset, u64 length, > ? ? ? ? ? ? ? ? ? ? ? struct nouveau_mem *); > - > +void nouveau_vm_map_sg_table(struct nouveau_vma *vma, u64 delta, u64 length, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ?struct nouveau_mem *mem); > ?/* nv50_vm.c */ > ?void nv50_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde, > ? ? ? ? ? ? ? ? ? ? struct nouveau_gpuobj *pgt[2]); > diff --git a/drivers/gpu/drm/nouveau/nv04_crtc.c > b/drivers/gpu/drm/nouveau/nv04_crtc.c > index 728d075..4c31c63 100644 > --- a/drivers/gpu/drm/nouveau/nv04_crtc.c > +++ b/drivers/gpu/drm/nouveau/nv04_crtc.c > @@ -1047,7 +1047,7 @@ nv04_crtc_create(struct drm_device *dev, int crtc_num) > ? ? ? ?drm_mode_crtc_set_gamma_size(&nv_crtc->base, 256); > > ? ? ? ?ret = nouveau_bo_new(dev, 64*64*4, 0x100, TTM_PL_FLAG_VRAM, > - ? ? ? ? ? ? ? ? ? ? ? ? ? ?0, 0x0000, &nv_crtc->cursor.nvbo); > + ? ? ? ? ? ? ? ? ? ? ? ? ? ?0, 0x0000, NULL, &nv_crtc->cursor.nvbo); > ? ? ? ?if (!ret) { > ? ? ? ? ? ? ? ?ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM); > ? ? ? ? ? ? ? ?if (!ret) > diff --git a/drivers/gpu/drm/nouveau/nv50_crtc.c > b/drivers/gpu/drm/nouveau/nv50_crtc.c > index 701b927..cad2abd 100644 > --- a/drivers/gpu/drm/nouveau/nv50_crtc.c > +++ b/drivers/gpu/drm/nouveau/nv50_crtc.c > @@ -769,7 +769,7 @@ nv50_crtc_create(struct drm_device *dev, int index) > ? ? ? ?nv_crtc->lut.depth = 0; > > ? ? ? ?ret = nouveau_bo_new(dev, 4096, 0x100, TTM_PL_FLAG_VRAM, > - ? ? ? ? ? ? ? ? ? ? ? ? ? ?0, 0x0000, &nv_crtc->lut.nvbo); > + ? ? ? ? ? ? ? ? ? ? ? ? ? ?0, 0x0000, NULL, &nv_crtc->lut.nvbo); > ? ? ? ?if (!ret) { > ? ? ? ? ? ? ? ?ret = nouveau_bo_pin(nv_crtc->lut.nvbo, TTM_PL_FLAG_VRAM); > ? ? ? ? ? ? ? ?if (!ret) > @@ -795,7 +795,7 @@ nv50_crtc_create(struct drm_device *dev, int index) > ? ? ? ?drm_mode_crtc_set_gamma_size(&nv_crtc->base, 256); > > ? ? ? ?ret = nouveau_bo_new(dev, 64*64*4, 0x100, TTM_PL_FLAG_VRAM, > - ? ? ? ? ? ? ? ? ? ? ? ? ? ?0, 0x0000, &nv_crtc->cursor.nvbo); > + ? ? ? ? ? ? ? ? ? ? ? ? ? ?0, 0x0000, NULL, &nv_crtc->cursor.nvbo); > ? ? ? ?if (!ret) { > ? ? ? ? ? ? ? ?ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM); > ? ? ? ? ? ? ? ?if (!ret) > diff --git a/drivers/gpu/drm/nouveau/nv50_evo.c > b/drivers/gpu/drm/nouveau/nv50_evo.c > index 9b962e9..ddcd555 100644 > --- a/drivers/gpu/drm/nouveau/nv50_evo.c > +++ b/drivers/gpu/drm/nouveau/nv50_evo.c > @@ -117,7 +117,7 @@ nv50_evo_channel_new(struct drm_device *dev, int chid, > ? ? ? ?evo->user_get = 4; > ? ? ? ?evo->user_put = 0; > > - ? ? ? ret = nouveau_bo_new(dev, 4096, 0, TTM_PL_FLAG_VRAM, 0, 0, > + ? ? ? ret = nouveau_bo_new(dev, 4096, 0, TTM_PL_FLAG_VRAM, 0, 0, NULL, > ? ? ? ? ? ? ? ? ? ? ? ? ? ? &evo->pushbuf_bo); > ? ? ? ?if (ret == 0) > ? ? ? ? ? ? ? ?ret = nouveau_bo_pin(evo->pushbuf_bo, TTM_PL_FLAG_VRAM); > @@ -333,7 +333,7 @@ nv50_evo_create(struct drm_device *dev) > ? ? ? ? ? ? ? ? ? ? ? ?goto err; > > ? ? ? ? ? ? ? ?ret = nouveau_bo_new(dev, 4096, 0x1000, TTM_PL_FLAG_VRAM, > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?0, 0x0000, &dispc->sem.bo); > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?0, 0x0000, NULL, &dispc->sem.bo); > ? ? ? ? ? ? ? ?if (!ret) { > ? ? ? ? ? ? ? ? ? ? ? ?ret = nouveau_bo_pin(dispc->sem.bo, TTM_PL_FLAG_VRAM); > ? ? ? ? ? ? ? ? ? ? ? ?if (!ret) > diff --git a/drivers/gpu/drm/nouveau/nvd0_display.c > b/drivers/gpu/drm/nouveau/nvd0_display.c > index 0247250..1f3a9b1 100644 > --- a/drivers/gpu/drm/nouveau/nvd0_display.c > +++ b/drivers/gpu/drm/nouveau/nvd0_display.c > @@ -882,7 +882,7 @@ nvd0_crtc_create(struct drm_device *dev, int index) > ? ? ? ?drm_mode_crtc_set_gamma_size(crtc, 256); > > ? ? ? ?ret = nouveau_bo_new(dev, 64 * 64 * 4, 0x100, TTM_PL_FLAG_VRAM, > - ? ? ? ? ? ? ? ? ? ? ? ? ? ?0, 0x0000, &nv_crtc->cursor.nvbo); > + ? ? ? ? ? ? ? ? ? ? ? ? ? ?0, 0x0000, NULL, &nv_crtc->cursor.nvbo); > ? ? ? ?if (!ret) { > ? ? ? ? ? ? ? ?ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM); > ? ? ? ? ? ? ? ?if (!ret) > @@ -895,7 +895,7 @@ nvd0_crtc_create(struct drm_device *dev, int index) > ? ? ? ? ? ? ? ?goto out; > > ? ? ? ?ret = nouveau_bo_new(dev, 8192, 0x100, TTM_PL_FLAG_VRAM, > - ? ? ? ? ? ? ? ? ? ? ? ? ? ?0, 0x0000, &nv_crtc->lut.nvbo); > + ? ? ? ? ? ? ? ? ? ? ? ? ? ?0, 0x0000, NULL, &nv_crtc->lut.nvbo); > ? ? ? ?if (!ret) { > ? ? ? ? ? ? ? ?ret = nouveau_bo_pin(nv_crtc->lut.nvbo, TTM_PL_FLAG_VRAM); > ? ? ? ? ? ? ? ?if (!ret) > @@ -2030,7 +2030,7 @@ nvd0_display_create(struct drm_device *dev) > > ? ? ? ?/* small shared memory area we use for notifiers and semaphores */ > ? ? ? ?ret = nouveau_bo_new(dev, 4096, 0x1000, TTM_PL_FLAG_VRAM, > - ? ? ? ? ? ? ? ? ? ? ? ? ? ?0, 0x0000, &disp->sync); > + ? ? ? ? ? ? ? ? ? ? ? ? ? ?0, 0x0000, NULL, &disp->sync); > ? ? ? ?if (!ret) { > ? ? ? ? ? ? ? ?ret = nouveau_bo_pin(disp->sync, TTM_PL_FLAG_VRAM); > ? ? ? ? ? ? ? ?if (!ret) > -- > 1.7.6 > > _______________________________________________ > dri-devel mailing list > dri-devel at lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/dri-devel