diff --git a/libdrm/intel/intel_bufmgr.h b/libdrm/intel/intel_bufmgr.h index c44d596..51b08a4 100644 --- a/libdrm/intel/intel_bufmgr.h +++ b/libdrm/intel/intel_bufmgr.h @@ -123,5 +123,7 @@ void intel_bo_fake_disable_backing_store(dri_bo *bo, void intel_bufmgr_fake_contended_lock_take(dri_bufmgr *bufmgr); void intel_bufmgr_fake_evict_all(dri_bufmgr *bufmgr); +int dri_gem_bo_map_gtt(dri_bo *bo, uint32_t alignment); + #endif /* INTEL_BUFMGR_H */ diff --git a/libdrm/intel/intel_bufmgr_gem.c b/libdrm/intel/intel_bufmgr_gem.c index 97e387f..af90a4f 100644 --- a/libdrm/intel/intel_bufmgr_gem.c +++ b/libdrm/intel/intel_bufmgr_gem.c @@ -39,6 +39,7 @@ #endif #include +#include #include #include #include @@ -46,6 +47,8 @@ #include #include #include +#include +#include #include "errno.h" #include "intel_bufmgr.h" @@ -517,6 +520,83 @@ dri_gem_bo_map(dri_bo *bo, int write_enable) return 0; } +int +dri_gem_bo_map_gtt(dri_bo *bo, uint32_t alignment) +{ + dri_bufmgr_gem *bufmgr_gem; + dri_bo_gem *bo_gem = (dri_bo_gem *)bo; + struct drm_i915_gem_set_domain set_domain; + int ret; + + bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr; + + /* Allow recursive mapping. Mesa may recursively map buffers with + * nested display loops. + */ + if (!bo_gem->mapped) { + + assert(bo->virtual == NULL); + + DBG("bo_map_gtt: %d (%s)\n", bo_gem->gem_handle, bo_gem->name); + + if (bo_gem->virtual == NULL) { + struct drm_i915_gem_mmap_gtt mmap_arg; + + memset(&mmap_arg, 0, sizeof(mmap_arg)); + mmap_arg.handle = bo_gem->gem_handle; + /* Just map the whole object */ + mmap_arg.offset = 0; + mmap_arg.size = bo->size; + mmap_arg.alignment = alignment; + + ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_MMAP_GTT, + &mmap_arg); + if (ret != 0) { + fprintf(stderr, + "%s:%d: Error preparing buffer map %d (%s): %s .\n", + __FILE__, __LINE__, + bo_gem->gem_handle, bo_gem->name, + strerror(errno)); + return ret; + } + bo_gem->virtual = mmap(0, bo->size, PROT_READ | PROT_WRITE, + MAP_SHARED, bufmgr_gem->fd, + mmap_arg.addr_ptr); + if (bo_gem->virtual == MAP_FAILED) { + fprintf(stderr, + "%s:%d: Error mapping buffer %d (%s): %s .\n", + __FILE__, __LINE__, + bo_gem->gem_handle, bo_gem->name, + strerror(errno)); + return errno; + } + } + + bo->virtual = bo_gem->virtual; + bo_gem->swrast = 0; + bo_gem->mapped = 1; + DBG("bo_map: %d (%s) -> %p\n", bo_gem->gem_handle, bo_gem->name, + bo_gem->virtual); + } + + if (!bo_gem->swrast) { + set_domain.handle = bo_gem->gem_handle; + set_domain.read_domains = I915_GEM_DOMAIN_GTT; + set_domain.write_domain = I915_GEM_DOMAIN_GTT; + do { + ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_SET_DOMAIN, + &set_domain); + } while (ret == -1 && errno == EINTR); + if (ret != 0) { + fprintf (stderr, "%s:%d: Error setting swrast %d: %s\n", + __FILE__, __LINE__, bo_gem->gem_handle, strerror (errno)); + } + bo_gem->swrast = 1; + } + + return 0; +} + static int dri_gem_bo_unmap(dri_bo *bo) { diff --git a/linux-core/i915_gem.c b/linux-core/i915_gem.c index 35dc5bd..11ffd02 100644 --- a/linux-core/i915_gem.c +++ b/linux-core/i915_gem.c @@ -31,6 +31,7 @@ #include "i915_drm.h" #include "i915_drv.h" #include +#include static int i915_gem_object_set_domain(struct drm_gem_object *obj, @@ -425,6 +426,8 @@ i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data, i915_gem_clflush_object(obj); drm_agp_chipset_flush(dev); } + + /* unmap here? */ drm_gem_object_unreference(obj); mutex_unlock(&dev->struct_mutex); return ret; @@ -471,6 +474,68 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data, return 0; } +extern unsigned long mmap_io_region(struct file *file, unsigned long addr, + unsigned long len, unsigned long flags, + unsigned int vm_flags, unsigned long pgoff, + int accountable); + +/** + * Maps the contents of an object into the GTT range, returning the address + * it is mapped into. + * + * While the mapping holds a reference on the contents of the object, it doesn't + * imply a ref on the object itself. + */ +int +i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_i915_gem_mmap_gtt *args = data; + struct drm_gem_object *obj; + struct drm_i915_gem_object *obj_priv; + loff_t offset; + unsigned long addr; + + if (!(dev->driver->driver_features & DRIVER_GEM)) + return -ENODEV; + + obj = drm_gem_object_lookup(dev, file_priv, args->handle); + if (obj == NULL) + return -EBADF; + + obj_priv = obj->driver_private; + offset = args->offset; + + /* No flags yet */ + if (args->flags) + return -EINVAL; + + /* Create a new mapping to be backed by a GTT range */ + addr = get_unmapped_area(obj->filp, 0, args->size, 0, + MAP_SHARED); + DRM_ERROR("%s: found unmapped area at 0x%08lx\n", __FUNCTION__, addr); + + //vma->vm_pgoff = (dev->agp->base + obj_priv->gtt_offset) >> PAGE_SHIFT; + /* Assuming the object is pinned, map it in the GTT range w/WC */ +// ret = pci_mmap_page_range(dev->pdev, vma, pci_mmap_mem, 1); + addr = mmap_io_region(obj->filp, addr, args->size, MAP_SHARED, + PROT_READ | PROT_WRITE | _PAGE_CACHE_WC, + (dev->agp->base + obj_priv->gtt_offset) >> PAGE_SHIFT, + 1); + + mutex_lock(&dev->struct_mutex); + drm_gem_object_unreference(obj); + mutex_unlock(&dev->struct_mutex); + if (IS_ERR((void *)addr)) { + DRM_ERROR("mmap_io_region failed: %ld\n", addr); + return addr; + } + + args->addr_ptr = (uint64_t) addr; + + return 0; +} + static void i915_gem_object_free_page_list(struct drm_gem_object *obj) { @@ -572,8 +637,6 @@ i915_add_request(struct drm_device *dev, uint32_t flush_domains) OUT_RING(MI_USER_INTERRUPT); ADVANCE_LP_RING(); - DRM_DEBUG("%d\n", seqno); - request->seqno = seqno; request->emitted_jiffies = jiffies; request->flush_domains = flush_domains; @@ -1748,6 +1811,7 @@ i915_gem_ring_throttle(struct drm_device *dev, struct drm_file *file_priv) seqno = i915_file_priv->mm.last_gem_throttle_seqno; i915_file_priv->mm.last_gem_throttle_seqno = i915_file_priv->mm.last_gem_seqno; + if (seqno) ret = i915_wait_request(dev, seqno); mutex_unlock(&dev->struct_mutex); @@ -2295,7 +2359,8 @@ i915_gem_init_hws(struct drm_device *dev) int ret; /* If we need a physical address for the status page, it's already - * initialized at driver load time. + * initialized at driver load time, unless kernel modesetting is + * active. */ if (!I915_NEED_GFX_HWS(dev)) return 0; diff --git a/shared-core/drm.h b/shared-core/drm.h index bb33282..05fc91d 100644 --- a/shared-core/drm.h +++ b/shared-core/drm.h @@ -236,7 +236,7 @@ enum drm_map_type { _DRM_AGP = 3, /**< AGP/GART */ _DRM_SCATTER_GATHER = 4, /**< Scatter/gather memory for PCI DMA */ _DRM_CONSISTENT = 5, /**< Consistent memory for PCI DMA */ - _DRM_TTM = 6 + _DRM_GEM = 6 }; /** diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index 619e6ac..e200917 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -1242,6 +1242,7 @@ struct drm_ioctl_desc i915_ioctls[] = { DRM_IOCTL_DEF(DRM_I915_GEM_PREAD, i915_gem_pread_ioctl, 0), DRM_IOCTL_DEF(DRM_I915_GEM_PWRITE, i915_gem_pwrite_ioctl, 0), DRM_IOCTL_DEF(DRM_I915_GEM_MMAP, i915_gem_mmap_ioctl, 0), + DRM_IOCTL_DEF(DRM_I915_GEM_MMAP_GTT, i915_gem_mmap_gtt_ioctl, 0), DRM_IOCTL_DEF(DRM_I915_GEM_SET_DOMAIN, i915_gem_set_domain_ioctl, 0), DRM_IOCTL_DEF(DRM_I915_GEM_SW_FINISH, i915_gem_sw_finish_ioctl, 0), DRM_IOCTL_DEF(DRM_I915_GEM_SET_TILING, i915_gem_set_tiling, 0), diff --git a/shared-core/i915_drm.h b/shared-core/i915_drm.h index 2801687..4b70df9 100644 --- a/shared-core/i915_drm.h +++ b/shared-core/i915_drm.h @@ -192,6 +192,7 @@ typedef struct drm_i915_sarea { #define DRM_I915_GEM_SW_FINISH 0x20 #define DRM_I915_GEM_SET_TILING 0x21 #define DRM_I915_GEM_GET_TILING 0x22 +#define DRM_I915_GEM_MMAP_GTT 0x23 #define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) #define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH) @@ -223,6 +224,7 @@ typedef struct drm_i915_sarea { #define DRM_IOCTL_I915_GEM_PREAD DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_PREAD, struct drm_i915_gem_pread) #define DRM_IOCTL_I915_GEM_PWRITE DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_PWRITE, struct drm_i915_gem_pwrite) #define DRM_IOCTL_I915_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MMAP, struct drm_i915_gem_mmap) +#define DRM_IOCTL_I915_GEM_MMAP_GTT DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MMAP_GTT, struct drm_i915_gem_mmap_gtt) #define DRM_IOCTL_I915_GEM_SET_DOMAIN DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_SET_DOMAIN, struct drm_i915_gem_set_domain) #define DRM_IOCTL_I915_GEM_SW_FINISH DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_SW_FINISH, struct drm_i915_gem_sw_finish) #define DRM_IOCTL_I915_GEM_SET_TILING DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_SET_TILING, struct drm_i915_gem_set_tiling) @@ -497,6 +499,24 @@ struct drm_i915_gem_mmap { uint64_t addr_ptr; /* void *, but pointers are not 32/64 compatible */ }; +struct drm_i915_gem_mmap_gtt { + /** Handle for the object being mapped. */ + uint32_t handle; + uint32_t pad; + /** Offset in the object to map. */ + uint64_t offset; + /** + * Length of data to map. + * + * The value will be page-aligned. + */ + uint64_t size; + /** Returned pointer the data was mapped at */ + uint64_t addr_ptr; /* void *, but pointers are not 32/64 compatible */ + uint32_t flags; + uint32_t alignment; +}; + struct drm_i915_gem_set_domain { /** Handle for the object */ uint32_t handle; diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index 48fd30d..32f2ce0 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -557,6 +557,8 @@ int i915_gem_pwrite_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); int i915_gem_mmap_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); +int i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); int i915_gem_set_domain_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); int i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data,