diff options
author | Dave Airlie <airlied@redhat.com> | 2010-03-18 10:03:50 +1000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2010-03-18 10:03:50 +1000 |
commit | 7c5cc4f63556e351e9e5980ed22accad410e3fdc (patch) | |
tree | 386470c130a79bd398244ca08b3d7a94b052cc25 | |
parent | 434eab575f8b3a29813faf911c238635703c2c49 (diff) |
drm: add support for multi-seat capability demonstration.
This is just a demo, it doesn't add any of the userspace interfaces
necessary for configuring multi-seat.
load drm module with gpgpu=1 option
this adds 3 render nodes, radeon then hardcodes the setup for my X1900
card so that one crtc + one DVI got to the first node, second crtc + one
DVI got to the second, and the third node has no output nodes at all.
aside changes include:
moving the dev_mapping to the minor node not per device - this means
in theory we could have a mapping range per node which might be cleaner
but may require pushing minor pointers further down.
no longer pushing inode down into drm_open_helper.
-rw-r--r-- | drivers/gpu/drm/drm_crtc.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_drv.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_fops.c | 29 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_stub.c | 47 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_vm.c | 16 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_gem.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_kms.c | 73 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_object.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_ttm.c | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/ttm/ttm_bo.c | 7 | ||||
-rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 5 | ||||
-rw-r--r-- | include/drm/drmP.h | 7 | ||||
-rw-r--r-- | include/drm/drm_crtc.h | 1 | ||||
-rw-r--r-- | include/drm/drm_mem_util.h | 3 | ||||
-rw-r--r-- | include/drm/ttm/ttm_bo_driver.h | 3 |
16 files changed, 176 insertions, 35 deletions
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index d91fb8c0b7b3..bc9ba0f061aa 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -897,6 +897,7 @@ int drm_mode_group_init(struct drm_device *dev, struct drm_mode_group *group) group->num_encoders = 0; return 0; } +EXPORT_SYMBOL(drm_mode_group_init); int drm_mode_group_init_legacy_group(struct drm_device *dev, struct drm_mode_group *group) diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index f3c58e2bd75c..62e4a5d92e0e 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -227,7 +227,7 @@ int drm_lastclose(struct drm_device * dev) !drm_core_check_feature(dev, DRIVER_MODESET)) drm_dma_takedown(dev); - dev->dev_mapping = NULL; + // dev->dev_mapping = NULL; mutex_unlock(&dev->struct_mutex); DRM_DEBUG("lastclose completed\n"); diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index 08d14df3bb42..a21f5acedc81 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -38,8 +38,8 @@ #include <linux/poll.h> #include <linux/smp_lock.h> -static int drm_open_helper(struct inode *inode, struct file *filp, - struct drm_device * dev); +static int drm_open_helper(struct file *filp, + struct drm_minor *minor); static int drm_setup(struct drm_device * dev) { @@ -128,7 +128,7 @@ int drm_open(struct inode *inode, struct file *filp) if (!(dev = minor->dev)) return -ENODEV; - retcode = drm_open_helper(inode, filp, dev); + retcode = drm_open_helper(filp, minor); if (!retcode) { atomic_inc(&dev->counts[_DRM_STAT_OPENS]); spin_lock(&dev->count_lock); @@ -141,11 +141,11 @@ int drm_open(struct inode *inode, struct file *filp) } out: mutex_lock(&dev->struct_mutex); - if (minor->type == DRM_MINOR_LEGACY) { - BUG_ON((dev->dev_mapping != NULL) && - (dev->dev_mapping != inode->i_mapping)); - if (dev->dev_mapping == NULL) - dev->dev_mapping = inode->i_mapping; + if (minor->type == DRM_MINOR_LEGACY || minor->type == DRM_MINOR_RENDER) { + BUG_ON((minor->dev_mapping != NULL) && + (minor->dev_mapping != inode->i_mapping)); + if (minor->dev_mapping == NULL) + minor->dev_mapping = inode->i_mapping; } mutex_unlock(&dev->struct_mutex); @@ -226,10 +226,10 @@ static int drm_cpu_valid(void) * Creates and initializes a drm_file structure for the file private data in \p * filp and add it into the double linked list in \p dev. */ -static int drm_open_helper(struct inode *inode, struct file *filp, - struct drm_device * dev) +static int drm_open_helper(struct file *filp, + struct drm_minor *minor) { - int minor_id = iminor(inode); + struct drm_device *dev = minor->dev; struct drm_file *priv; int ret; @@ -238,7 +238,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp, if (!drm_cpu_valid()) return -EINVAL; - DRM_DEBUG("pid = %d, minor = %d\n", task_pid_nr(current), minor_id); + DRM_DEBUG("pid = %d, minor = %d\n", task_pid_nr(current), minor->index); priv = kmalloc(sizeof(*priv), GFP_KERNEL); if (!priv) @@ -249,7 +249,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp, priv->filp = filp; priv->uid = current_euid(); priv->pid = task_pid_nr(current); - priv->minor = idr_find(&drm_minors_idr, minor_id); + priv->minor = minor; priv->ioctl_count = 0; /* for compatibility root is always authenticated */ priv->authenticated = capable(CAP_SYS_ADMIN); @@ -552,7 +552,8 @@ int drm_release(struct inode *inode, struct file *filp) } /* drop the reference held my the file priv */ - drm_master_put(&file_priv->master); + if (file_priv->master) + drm_master_put(&file_priv->master); file_priv->is_master = 0; list_del(&file_priv->lhead); mutex_unlock(&dev->struct_mutex); diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c index ad73e141afdb..22c62501aa68 100644 --- a/drivers/gpu/drm/drm_stub.c +++ b/drivers/gpu/drm/drm_stub.c @@ -39,6 +39,9 @@ unsigned int drm_debug = 0; /* 1 to enable debug output */ EXPORT_SYMBOL(drm_debug); +unsigned int drm_gpgpu = 0; +EXPORT_SYMBOL(drm_gpgpu); + MODULE_AUTHOR(CORE_AUTHOR); MODULE_DESCRIPTION(CORE_DESC); MODULE_LICENSE("GPL and additional rights"); @@ -46,6 +49,9 @@ MODULE_PARM_DESC(debug, "Enable debug output"); module_param_named(debug, drm_debug, int, 0600); +MODULE_PARM_DESC(gpgpu, "Enable GPGPU render node by default"); +module_param_named(gpgpu, drm_gpgpu, int, 0400); + struct idr drm_minors_idr; struct class *drm_class; @@ -234,6 +240,7 @@ static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev, INIT_LIST_HEAD(&dev->vmalist); INIT_LIST_HEAD(&dev->maplist); INIT_LIST_HEAD(&dev->vblank_event_list); + INIT_LIST_HEAD(&dev->render_minor_list); spin_lock_init(&dev->count_lock); spin_lock_init(&dev->drw_lock); @@ -343,6 +350,7 @@ static int drm_get_minor(struct drm_device *dev, struct drm_minor **minor, int t new_minor->dev = dev; new_minor->index = minor_id; INIT_LIST_HEAD(&new_minor->master_list); + INIT_LIST_HEAD(&new_minor->render_node_list); idr_replace(&drm_minors_idr, new_minor, minor_id); @@ -386,6 +394,29 @@ err_idr: return ret; } +int drm_create_minor_render(struct drm_device *dev, struct drm_minor **minor_p) +{ + int ret; + struct drm_minor *minor; + + ret = drm_get_minor(dev, &minor, DRM_MINOR_RENDER); + if (ret) + return ret; + + list_add_tail(&minor->render_node_list, &dev->render_minor_list); + return 0; +} + +int drm_destroy_minor_render(struct drm_device *dev) +{ + struct drm_minor *minor, *tmp; + + list_for_each_entry_safe(minor, tmp, &dev->render_minor_list, render_node_list) { + drm_put_minor(&minor); + } + return 0; +} + /** * Register. * @@ -424,6 +455,15 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent, ret = drm_get_minor(dev, &dev->control, DRM_MINOR_CONTROL); if (ret) goto err_g2; + + if (drm_gpgpu) { + int i; + for (i = 0; i < 3; i++) { + struct drm_minor *test_minor; + + drm_create_minor_render(dev, &test_minor); + } + } } if ((ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY))) @@ -479,6 +519,8 @@ int drm_put_minor(struct drm_minor **minor_p) DRM_DEBUG("release secondary minor %d\n", minor->index); + list_del(&minor->render_node_list); + if (minor->type == DRM_MINOR_LEGACY) drm_proc_cleanup(minor, drm_proc_root); #if defined(CONFIG_DEBUG_FS) @@ -542,9 +584,12 @@ void drm_put_dev(struct drm_device *dev) drm_ctxbitmap_cleanup(dev); - if (drm_core_check_feature(dev, DRIVER_MODESET)) + if (drm_core_check_feature(dev, DRIVER_MODESET)) { drm_put_minor(&dev->control); + drm_destroy_minor_render(dev); + } + if (driver->driver_features & DRIVER_GEM) drm_gem_destroy(dev); diff --git a/drivers/gpu/drm/drm_vm.c b/drivers/gpu/drm/drm_vm.c index 4ac900f4647f..13d9e2b13314 100644 --- a/drivers/gpu/drm/drm_vm.c +++ b/drivers/gpu/drm/drm_vm.c @@ -676,3 +676,19 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma) return ret; } EXPORT_SYMBOL(drm_mmap); + +void drm_unmap_mapping(struct drm_device *dev, loff_t const holebegin, + loff_t const holelen) +{ + struct drm_minor *minor; + if (dev->primary->dev_mapping) + unmap_mapping_range(dev->primary->dev_mapping, + holebegin, holelen, 1); + + list_for_each_entry(minor, &dev->render_minor_list, render_node_list) { + if (minor->dev_mapping) + unmap_mapping_range(minor->dev_mapping, + holebegin, holelen, 1); + } +} +EXPORT_SYMBOL(drm_unmap_mapping); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index fba37e9f775d..5c9de6fa200a 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1306,9 +1306,7 @@ i915_gem_release_mmap(struct drm_gem_object *obj) struct drm_device *dev = obj->dev; struct drm_i915_gem_object *obj_priv = obj->driver_private; - if (dev->dev_mapping) - unmap_mapping_range(dev->dev_mapping, - obj_priv->mmap_offset, obj->size, 1); + drm_unmap_mapping(dev, obj_priv->mmap_offset, obj->size); } static void diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 0d22f66f1c79..5934201088c3 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -136,8 +136,8 @@ nouveau_gem_ioctl_new(struct drm_device *dev, void *data, NOUVEAU_CHECK_INITIALISED_WITH_RETURN; - if (unlikely(dev_priv->ttm.bdev.dev_mapping == NULL)) - dev_priv->ttm.bdev.dev_mapping = dev_priv->dev->dev_mapping; + if (unlikely(dev_priv->ttm.bdev.mapping_priv == NULL)) + dev_priv->ttm.bdev.mapping_priv = (void *)dev; if (req->channel_hint) { NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(req->channel_hint, diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index 20ec276e7596..22e125a48f33 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c @@ -31,7 +31,7 @@ #include "radeon_drm.h" #include <linux/vga_switcheroo.h> - +extern int drm_gpgpu; int radeon_driver_unload_kms(struct drm_device *dev) { struct radeon_device *rdev = dev->dev_private; @@ -45,6 +45,72 @@ int radeon_driver_unload_kms(struct drm_device *dev) return 0; } +static int radeon_init_render_nodes(struct drm_device *dev) +{ + struct drm_minor *minor; + struct drm_connector *connector; + struct drm_crtc *crtc; + struct drm_mode_group *group; + int i = 0, j = 0; + int ret = 0; + + list_for_each_entry(minor, &dev->render_minor_list, render_node_list) { + struct drm_connector *this_connector; + + group = &minor->mode_group; + if (i == 2) + break; + /* initialise a mode group */ + ret = drm_mode_group_init(dev, &minor->mode_group); + if (ret) + goto out; + j = 0; + this_connector = NULL; + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + /* TODO de-hardcode */ + if ((i == 0 && j == 0) || (i == 1 && j == 2)) { + this_connector = connector; + printk("pick connector %d for minor num %d\n", connector->base.id, i); + break; + } + j++; + } + + if (!this_connector) { + printk("connector skip for %d\n", i); + goto next_one; + } + + j = 0; + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + if (i == j) { + printk("pick crtc %d for minor num %d\n", crtc->base.id, i); + group->id_list[group->num_crtcs++] = crtc->base.id; + break; + } + j++; + } + + for (j = 0; j < DRM_CONNECTOR_MAX_ENCODER; j++) { + if (this_connector->encoder_ids[j] != 0) + group->id_list[group->num_crtcs + group->num_encoders++] = this_connector->encoder_ids[j]; + } + + group->id_list[group->num_crtcs + group->num_encoders + group->num_connectors++] = this_connector->base.id; + + next_one: + printk("node %d %d %d %d", minor->index, group->num_crtcs, group->num_encoders, group->num_connectors); + for (j = 0; j < group->num_crtcs + group->num_encoders + group->num_connectors; j++) + printk("%d ", group->id_list[j]); + printk("\n"); + i++; + } + + +out: + return ret; +} + int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags) { struct radeon_device *rdev; @@ -83,6 +149,11 @@ int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags) r = radeon_modeset_init(rdev); if (r) dev_err(&dev->pdev->dev, "Fatal error during modeset init\n"); + + /* assign group resources to the render minors */ + if (drm_gpgpu) { + radeon_init_render_nodes(dev); + } out: if (r) radeon_driver_unload_kms(dev); diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index fc9d00ac6b15..c0f58211581c 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -92,8 +92,8 @@ int radeon_bo_create(struct radeon_device *rdev, struct drm_gem_object *gobj, enum ttm_bo_type type; int r; - if (unlikely(rdev->mman.bdev.dev_mapping == NULL)) { - rdev->mman.bdev.dev_mapping = rdev->ddev->dev_mapping; + if (unlikely(rdev->mman.bdev.mapping_priv == NULL)) { + rdev->mman.bdev.mapping_priv = (void *)rdev->ddev; } if (kernel) { type = ttm_bo_type_kernel; diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index 43c5ab34b634..2635048cc68c 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -529,8 +529,9 @@ int radeon_ttm_init(struct radeon_device *rdev) } DRM_INFO("radeon: %uM of GTT memory ready.\n", (unsigned)(rdev->mc.gtt_size / (1024 * 1024))); - if (unlikely(rdev->mman.bdev.dev_mapping == NULL)) { - rdev->mman.bdev.dev_mapping = rdev->ddev->dev_mapping; + + if (unlikely(rdev->mman.bdev.mapping_priv == NULL)) { + rdev->mman.bdev.mapping_priv = (void *)rdev->ddev; } r = radeon_ttm_debugfs_init(rdev); diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 9db02bb3e3fe..a97962edfd87 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -45,6 +45,7 @@ #include <linux/mm.h> #include <linux/file.h> #include <linux/module.h> +#include "drm/drm_mem_util.h" #define TTM_ASSERT_LOCKED(param) #define TTM_DEBUG(fmt, arg...) @@ -1516,7 +1517,7 @@ int ttm_bo_device_init(struct ttm_bo_device *bdev, INIT_DELAYED_WORK(&bdev->wq, ttm_bo_delayed_workqueue); bdev->nice_mode = true; INIT_LIST_HEAD(&bdev->ddestroy); - bdev->dev_mapping = NULL; + bdev->mapping_priv = NULL; bdev->glob = glob; bdev->need_dma32 = need_dma32; @@ -1579,10 +1580,10 @@ void ttm_bo_unmap_virtual(struct ttm_buffer_object *bo) loff_t offset = (loff_t) bo->addr_space_offset; loff_t holelen = ((loff_t) bo->mem.num_pages) << PAGE_SHIFT; - if (!bdev->dev_mapping) + if (!bdev->mapping_priv) return; - unmap_mapping_range(bdev->dev_mapping, offset, holelen, 1); + drm_unmap_mapping(bdev->mapping_priv, offset, holelen); } EXPORT_SYMBOL(ttm_bo_unmap_virtual); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 0c9c0811f42d..b29019131752 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -461,9 +461,8 @@ static int vmw_driver_open(struct drm_device *dev, struct drm_file *file_priv) file_priv->driver_priv = vmw_fp; - if (unlikely(dev_priv->bdev.dev_mapping == NULL)) - dev_priv->bdev.dev_mapping = - file_priv->filp->f_path.dentry->d_inode->i_mapping; + if (unlikely(dev_priv->bdev.mapping_priv == NULL)) + dev_priv->bdev.mapping_priv = (void *)dev; return 0; diff --git a/include/drm/drmP.h b/include/drm/drmP.h index de2f82efb15f..13c1efb7b305 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -891,6 +891,10 @@ struct drm_minor { struct drm_master *master; /* currently active master for this node */ struct list_head master_list; struct drm_mode_group mode_group; + + struct address_space *dev_mapping; + + struct list_head render_node_list; }; struct drm_pending_vblank_event { @@ -1024,7 +1028,6 @@ struct drm_device { int num_crtcs; /**< Number of CRTCs on this device */ void *dev_private; /**< device private data */ void *mm_private; - struct address_space *dev_mapping; struct drm_sigdata sigdata; /**< For block_all_signals */ sigset_t sigmask; @@ -1033,7 +1036,7 @@ struct drm_device { unsigned int agp_buffer_token; struct drm_minor *control; /**< Control node for card */ struct drm_minor *primary; /**< render type primary screen head */ - + struct list_head render_minor_list; /** \name Drawable information */ /*@{ */ spinlock_t drw_lock; diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 1347524a8e30..d93d784ae7ef 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -663,6 +663,7 @@ extern char *drm_get_dvi_i_select_name(int val); extern char *drm_get_tv_subconnector_name(int val); extern char *drm_get_tv_select_name(int val); extern void drm_fb_release(struct drm_file *file_priv); +extern int drm_mode_group_init(struct drm_device *dev, struct drm_mode_group *group); extern int drm_mode_group_init_legacy_group(struct drm_device *dev, struct drm_mode_group *group); extern struct edid *drm_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter); diff --git a/include/drm/drm_mem_util.h b/include/drm/drm_mem_util.h index 6bd325fedc87..820afbb7a7aa 100644 --- a/include/drm/drm_mem_util.h +++ b/include/drm/drm_mem_util.h @@ -62,4 +62,7 @@ static __inline void drm_free_large(void *ptr) vfree(ptr); } +struct drm_device; +extern void drm_unmap_mapping(struct drm_device *dev, loff_t const holebegin, + loff_t const holelen); #endif diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index e929c27ede22..755cd619b6e3 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -38,6 +38,7 @@ #include "linux/fs.h" #include "linux/spinlock.h" +struct drm_device; struct ttm_backend; struct ttm_backend_func { @@ -464,7 +465,7 @@ struct ttm_bo_device { */ bool nice_mode; - struct address_space *dev_mapping; + struct drm_device *mapping_priv; /* * Internal protection. |