summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2010-03-18 10:03:50 +1000
committerDave Airlie <airlied@redhat.com>2010-03-18 10:03:50 +1000
commit7c5cc4f63556e351e9e5980ed22accad410e3fdc (patch)
tree386470c130a79bd398244ca08b3d7a94b052cc25
parent434eab575f8b3a29813faf911c238635703c2c49 (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.c1
-rw-r--r--drivers/gpu/drm/drm_drv.c2
-rw-r--r--drivers/gpu/drm/drm_fops.c29
-rw-r--r--drivers/gpu/drm/drm_stub.c47
-rw-r--r--drivers/gpu/drm/drm_vm.c16
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c4
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_gem.c4
-rw-r--r--drivers/gpu/drm/radeon/radeon_kms.c73
-rw-r--r--drivers/gpu/drm/radeon/radeon_object.c4
-rw-r--r--drivers/gpu/drm/radeon/radeon_ttm.c5
-rw-r--r--drivers/gpu/drm/ttm/ttm_bo.c7
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_drv.c5
-rw-r--r--include/drm/drmP.h7
-rw-r--r--include/drm/drm_crtc.h1
-rw-r--r--include/drm/drm_mem_util.h3
-rw-r--r--include/drm/ttm/ttm_bo_driver.h3
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.