From patchwork Mon Mar 8 06:37:35 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dave Airlie X-Patchwork-Id: 84009 Received: from lists.sourceforge.net (lists.sourceforge.net [216.34.181.88]) by demeter.kernel.org (8.14.3/8.14.3) with ESMTP id o287NuZR024965 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Mon, 8 Mar 2010 07:24:33 GMT Received: from localhost ([127.0.0.1] helo=sfs-ml-3.v29.ch3.sourceforge.com) by sfs-ml-3.v29.ch3.sourceforge.com with esmtp (Exim 4.69) (envelope-from ) id 1NoXIW-0002WA-TF; Mon, 08 Mar 2010 07:22:40 +0000 Received: from sfi-mx-3.v28.ch3.sourceforge.com ([172.29.28.123] helo=mx.sourceforge.net) by sfs-ml-3.v29.ch3.sourceforge.com with esmtp (Exim 4.69) (envelope-from ) id 1NoXIV-0002W5-MC for dri-devel@lists.sourceforge.net; Mon, 08 Mar 2010 07:22:39 +0000 Received-SPF: neutral (sfi-mx-3.v28.ch3.sourceforge.com: 209.132.183.28 is neither permitted nor denied by domain of gmail.com) client-ip=209.132.183.28; envelope-from=airlied@gmail.com; helo=mx1.redhat.com; Received: from mx1.redhat.com ([209.132.183.28]) by sfi-mx-3.v28.ch3.sourceforge.com with esmtp (Exim 4.69) id 1NoXIU-00018O-AQ for dri-devel@lists.sourceforge.net; Mon, 08 Mar 2010 07:22:39 +0000 Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id o286anPO003895 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Mon, 8 Mar 2010 01:36:49 -0500 Received: from localhost.localdomain (dhcp-0-222.bne.redhat.com [10.64.0.222]) by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id o286al6u012145 for ; Mon, 8 Mar 2010 01:36:48 -0500 From: Dave Airlie To: dri-devel@lists.sf.net Subject: [PATCH] [RFC] drm: dumb scanout create/mmap for intel/radeon Date: Mon, 8 Mar 2010 16:37:35 +1000 Message-Id: <1268030255-13422-1-git-send-email-airlied@gmail.com> X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 X-Spam-Score: 0.6 (/) X-Spam-Report: Spam Filtering performed by mx.sourceforge.net. See http://spamassassin.org/tag/ for more details. -0.0 SPF_HELO_PASS SPF: HELO matches SPF record 1.2 SPF_NEUTRAL SPF: sender does not match SPF record (neutral) -0.6 AWL AWL: From: address is in the auto white-list X-Headers-End: 1NoXIU-00018O-AQ X-BeenThere: dri-devel@lists.sourceforge.net X-Mailman-Version: 2.1.9 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: dri-devel-bounces@lists.sourceforge.net X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter.kernel.org [140.211.167.41]); Mon, 08 Mar 2010 07:24:33 +0000 (UTC) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index d91fb8c..8d2e997 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -2653,3 +2653,26 @@ out: mutex_unlock(&dev->mode_config.mutex); return ret; } + +int drm_mode_create_dumb_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv) +{ + struct drm_mode_create_dumb *args = data; + + if (!dev->driver->dumb_create) + return -ENOSYS; + + return dev->driver->dumb_create(file_priv, dev, args->size, &args->handle); +} + +int drm_mode_mmap_dumb_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv) +{ + struct drm_mode_map_dumb *args = data; + + /* call driver ioctl to get mmap offset */ + if (!dev->driver->dumb_map_offset) + return -ENOSYS; + + return dev->driver->dumb_map_offset(file_priv, dev, args->handle, &args->offset); +} diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index f3c58e2..4a3b007 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -146,7 +146,9 @@ static struct drm_ioctl_desc drm_ioctls[] = { DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), DRM_IOCTL_DEF(DRM_IOCTL_MODE_PAGE_FLIP, drm_mode_page_flip_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED) + DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATE_DUMB, drm_mode_create_dumb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_MAP_DUMB, drm_mode_mmap_dumb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED) }; #define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls ) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 1b2e954..3a07392 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -526,6 +526,8 @@ static struct drm_driver driver = { .gem_init_object = i915_gem_init_object, .gem_free_object = i915_gem_free_object, .gem_vm_ops = &i915_gem_vm_ops, + .dumb_create = i915_gem_dumb_create, + .dumb_map_offset = i915_gem_mmap_gtt, .ioctls = i915_ioctls, .fops = { .owner = THIS_MODULE, diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 979439c..5bf054c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -930,6 +930,11 @@ void i915_gem_object_flush_write_domain(struct drm_gem_object *obj); void i915_gem_shrinker_init(void); void i915_gem_shrinker_exit(void); +int i915_gem_dumb_create(struct drm_file *file_priv, + struct drm_device *dev, uint64_t size, + uint32_t *handle_p); +int i915_gem_mmap_gtt(struct drm_file *file_priv, struct drm_device *dev, + uint32_t handle, uint64_t *offset); /* i915_gem_tiling.c */ void i915_gem_detect_bit_6_swizzle(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index fba37e9..1f1e8c6 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -107,23 +107,23 @@ i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data, return 0; } - /** * Creates a new mm object and returns a handle to it. */ int -i915_gem_create_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) +i915_gem_dumb_create(struct drm_file *file_priv, + struct drm_device *dev, uint64_t size, + uint32_t *handle_p) + { - struct drm_i915_gem_create *args = data; struct drm_gem_object *obj; int ret; u32 handle; - args->size = roundup(args->size, PAGE_SIZE); + size = roundup(size, PAGE_SIZE); /* Allocate the new object */ - obj = drm_gem_object_alloc(dev, args->size); + obj = drm_gem_object_alloc(dev, size); if (obj == NULL) return -ENOMEM; @@ -133,10 +133,21 @@ i915_gem_create_ioctl(struct drm_device *dev, void *data, if (ret) return ret; - args->handle = handle; + *handle_p = handle; return 0; } +/** + * Creates a new mm object and returns a handle to it. + */ +int +i915_gem_create_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_i915_gem_create *args = data; + return i915_gem_dumb_create(file_priv, dev, + args->size, &args->handle); +} static inline int fast_shmem_read(struct page **pages, @@ -1371,35 +1382,18 @@ i915_gem_get_gtt_alignment(struct drm_gem_object *obj) return i; } -/** - * i915_gem_mmap_gtt_ioctl - prepare an object for GTT mmap'ing - * @dev: DRM device - * @data: GTT mapping ioctl data - * @file_priv: GEM object info - * - * Simply returns the fake offset to userspace so it can mmap it. - * The mmap call will end up in drm_gem_mmap(), which will set things - * up so we can get faults in the handler above. - * - * The fault handler will take care of binding the object into the GTT - * (since it may have been evicted to make room for something), allocating - * a fence register, and mapping the appropriate aperture address into - * userspace. - */ int -i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) +i915_gem_mmap_gtt(struct drm_file *file_priv, + struct drm_device *dev, + uint32_t handle, + uint64_t *offset) { - struct drm_i915_gem_mmap_gtt *args = data; struct drm_i915_private *dev_priv = dev->dev_private; struct drm_gem_object *obj; struct drm_i915_gem_object *obj_priv; int ret; - if (!(dev->driver->driver_features & DRIVER_GEM)) - return -ENODEV; - - obj = drm_gem_object_lookup(dev, file_priv, args->handle); + obj = drm_gem_object_lookup(dev, file_priv, handle); if (obj == NULL) return -EBADF; @@ -1424,7 +1418,7 @@ i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data, } } - args->offset = obj_priv->mmap_offset; + *offset = obj_priv->mmap_offset; /* * Pull it into the GTT so that we have a page list (makes the @@ -1439,13 +1433,39 @@ i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data, } list_add_tail(&obj_priv->list, &dev_priv->mm.inactive_list); } - + drm_gem_object_unreference(obj); mutex_unlock(&dev->struct_mutex); - return 0; } +/** + * i915_gem_mmap_gtt_ioctl - prepare an object for GTT mmap'ing + * @dev: DRM device + * @data: GTT mapping ioctl data + * @file_priv: GEM object info + * + * Simply returns the fake offset to userspace so it can mmap it. + * The mmap call will end up in drm_gem_mmap(), which will set things + * up so we can get faults in the handler above. + * + * The fault handler will take care of binding the object into the GTT + * (since it may have been evicted to make room for something), allocating + * a fence register, and mapping the appropriate aperture address into + * userspace. + */ +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; + + if (!(dev->driver->driver_features & DRIVER_GEM)) + return -ENODEV; + + return i915_gem_mmap_gtt(file_priv, dev, args->handle, &args->offset); +} + void i915_gem_object_put_pages(struct drm_gem_object *obj) { @@ -5165,3 +5185,5 @@ i915_gem_shrinker_exit(void) { unregister_shrinker(&shrinker); } + + diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 6eec0ec..a714cfd 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -71,6 +71,12 @@ void radeon_gem_object_free(struct drm_gem_object *obj); extern struct drm_ioctl_desc radeon_ioctls_kms[]; extern int radeon_max_kms_ioctl; int radeon_mmap(struct file *filp, struct vm_area_struct *vma); +int radeon_mode_dumb_mmap(struct drm_file *filp, + struct drm_device *dev, + uint32_t handle, uint64_t *offset_p); +int radeon_mode_dumb_create(struct drm_file *file_priv, + struct drm_device *dev, uint64_t size, uint32_t *handle_p); + #if defined(CONFIG_DEBUG_FS) int radeon_debugfs_init(struct drm_minor *minor); void radeon_debugfs_cleanup(struct drm_minor *minor); @@ -286,6 +292,8 @@ static struct drm_driver kms_driver = { .gem_init_object = radeon_gem_object_init, .gem_free_object = radeon_gem_object_free, .dma_ioctl = radeon_dma_ioctl_kms, + .dumb_create = radeon_mode_dumb_create, + .dumb_map_offset = radeon_mode_dumb_mmap, .fops = { .owner = THIS_MODULE, .open = drm_open, diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c index ef92d14..f16a4c7 100644 --- a/drivers/gpu/drm/radeon/radeon_gem.c +++ b/drivers/gpu/drm/radeon/radeon_gem.c @@ -234,23 +234,31 @@ int radeon_gem_set_domain_ioctl(struct drm_device *dev, void *data, return r; } -int radeon_gem_mmap_ioctl(struct drm_device *dev, void *data, - struct drm_file *filp) +int radeon_mode_dumb_mmap(struct drm_file *filp, + struct drm_device *dev, + uint32_t handle, uint64_t *offset_p) { - struct drm_radeon_gem_mmap *args = data; struct drm_gem_object *gobj; struct radeon_bo *robj; - - gobj = drm_gem_object_lookup(dev, filp, args->handle); + + gobj = drm_gem_object_lookup(dev, filp, handle); if (gobj == NULL) { return -EINVAL; } robj = gobj->driver_private; - args->addr_ptr = radeon_bo_mmap_offset(robj); + *offset_p = radeon_bo_mmap_offset(robj); drm_gem_object_unreference_unlocked(gobj); return 0; } +int radeon_gem_mmap_ioctl(struct drm_device *dev, void *data, + struct drm_file *filp) +{ + struct drm_radeon_gem_mmap *args = data; + + return radeon_mode_dumb_mmap(filp, dev, args->handle, &args->addr_ptr); +} + int radeon_gem_busy_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) { @@ -343,3 +351,31 @@ out: drm_gem_object_unreference_unlocked(gobj); return r; } + +int radeon_mode_dumb_create(struct drm_file *file_priv, + struct drm_device *dev, uint64_t size, uint32_t *handle_p) +{ + struct radeon_device *rdev = dev->dev_private; + struct drm_gem_object *gobj; + int r; + uint32_t handle; + + size = ALIGN(size, PAGE_SIZE); + + r = radeon_gem_object_create(rdev, size, 0, + RADEON_GEM_DOMAIN_VRAM, + false, ttm_bo_type_device, + &gobj); + if (r) + return -ENOMEM; + + r = drm_gem_handle_create(file_priv, gobj, &handle); + if (r) { + drm_gem_object_unreference_unlocked(gobj); + return r; + } + drm_gem_object_handle_unreference_unlocked(gobj); + *handle_p = handle; + return 0; +} + diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 1702b82..832d056 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -575,4 +575,6 @@ void radeon_legacy_tv_adjust_pll2(struct drm_encoder *encoder, void radeon_legacy_tv_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode); + + #endif diff --git a/include/drm/drm.h b/include/drm/drm.h index e3f46e0..8a9bd6f 100644 --- a/include/drm/drm.h +++ b/include/drm/drm.h @@ -699,6 +699,9 @@ struct drm_gem_open { #define DRM_IOCTL_MODE_PAGE_FLIP DRM_IOWR(0xB0, struct drm_mode_crtc_page_flip) #define DRM_IOCTL_MODE_DIRTYFB DRM_IOWR(0xB1, struct drm_mode_fb_dirty_cmd) +#define DRM_IOCTL_MODE_CREATE_DUMB DRM_IOWR(0xB0, struct drm_mode_create_dumb) +#define DRM_IOCTL_MODE_MAP_DUMB DRM_IOWR(0xB1, struct drm_mode_map_dumb) + /** * Device specific ioctls should only be in their respective headers * The device specific ioctl range is from 0x40 to 0x99. diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 4a3c4e4..d0933d0 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -806,6 +806,14 @@ struct drm_driver { /* vga arb irq handler */ void (*vgaarb_irq)(struct drm_device *dev, bool state); + /* dumb alloc support */ + int (*dumb_create)(struct drm_file *file_priv, + struct drm_device *dev, uint64_t size, + uint32_t *handle); + int (*dumb_map_offset)(struct drm_file *file_priv, + struct drm_device *dev, uint32_t handle, + uint64_t *offset); + /* Driver private ops for this object */ struct vm_operations_struct *gem_vm_ops; diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 1347524..4f8543c 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -803,4 +803,10 @@ extern int drm_add_modes_noedid(struct drm_connector *connector, int hdisplay, int vdisplay); extern bool drm_edid_is_valid(struct edid *edid); + +extern int drm_mode_create_dumb_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv); +extern int drm_mode_mmap_dumb_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv); + #endif /* __DRM_CRTC_H__ */ diff --git a/include/drm/drm_mode.h b/include/drm/drm_mode.h index c5ba163..c72d741 100644 --- a/include/drm/drm_mode.h +++ b/include/drm/drm_mode.h @@ -343,4 +343,24 @@ struct drm_mode_crtc_page_flip { __u64 user_data; }; +/* create a dumb scanout buffer */ +struct drm_mode_create_dumb { + uint64_t size; + uint32_t handle; + uint32_t flags; +}; + +/* set up for mmap of a dumb scanout buffer */ +struct drm_mode_map_dumb { + /** Handle for the object being mapped. */ + __u32 handle; + __u32 pad; + /** + * Fake offset to use for subsequent mmap call + * + * This is a fixed-size type for 32/64 compatibility. + */ + __u64 offset; +}; + #endif