diff options
author | Dave Airlie <airlied@redhat.com> | 2008-11-27 23:22:24 -0500 |
---|---|---|
committer | Dave Airlie <airlied@linux.ie> | 2008-12-29 02:47:22 -0500 |
commit | 7c1c2871a6a3a114853ec6836e9035ac1c0c7f7a (patch) | |
tree | 1b5debcc86ff20bd5e11b42ea5c52da42214e376 /drivers/gpu/drm/drm_stub.c | |
parent | e7f7ab45ebcb54fd5f814ea15ea079e079662f67 (diff) |
drm: move to kref per-master structures.
This is step one towards having multiple masters sharing a drm
device in order to get fast-user-switching to work.
It splits out the information associated with the drm master
into a separate kref counted structure, and allocates this when
a master opens the device node. It also allows the current master
to abdicate (say while VT switched), and a new master to take over
the hardware.
It moves the Intel and radeon drivers to using the sarea from
within the new master structures.
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/drm_stub.c')
-rw-r--r-- | drivers/gpu/drm/drm_stub.c | 105 |
1 files changed, 99 insertions, 6 deletions
diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c index 849c0a9fe7fd..0f24c2dcd517 100644 --- a/drivers/gpu/drm/drm_stub.c +++ b/drivers/gpu/drm/drm_stub.c | |||
@@ -79,6 +79,104 @@ again: | |||
79 | return new_id; | 79 | return new_id; |
80 | } | 80 | } |
81 | 81 | ||
82 | struct drm_master *drm_master_create(struct drm_minor *minor) | ||
83 | { | ||
84 | struct drm_master *master; | ||
85 | |||
86 | master = drm_calloc(1, sizeof(*master), DRM_MEM_DRIVER); | ||
87 | if (!master) | ||
88 | return NULL; | ||
89 | |||
90 | kref_init(&master->refcount); | ||
91 | spin_lock_init(&master->lock.spinlock); | ||
92 | init_waitqueue_head(&master->lock.lock_queue); | ||
93 | drm_ht_create(&master->magiclist, DRM_MAGIC_HASH_ORDER); | ||
94 | INIT_LIST_HEAD(&master->magicfree); | ||
95 | master->minor = minor; | ||
96 | |||
97 | list_add_tail(&master->head, &minor->master_list); | ||
98 | |||
99 | return master; | ||
100 | } | ||
101 | |||
102 | struct drm_master *drm_master_get(struct drm_master *master) | ||
103 | { | ||
104 | kref_get(&master->refcount); | ||
105 | return master; | ||
106 | } | ||
107 | |||
108 | static void drm_master_destroy(struct kref *kref) | ||
109 | { | ||
110 | struct drm_master *master = container_of(kref, struct drm_master, refcount); | ||
111 | struct drm_magic_entry *pt, *next; | ||
112 | struct drm_device *dev = master->minor->dev; | ||
113 | |||
114 | list_del(&master->head); | ||
115 | |||
116 | if (dev->driver->master_destroy) | ||
117 | dev->driver->master_destroy(dev, master); | ||
118 | |||
119 | if (master->unique) { | ||
120 | drm_free(master->unique, strlen(master->unique) + 1, DRM_MEM_DRIVER); | ||
121 | master->unique = NULL; | ||
122 | master->unique_len = 0; | ||
123 | } | ||
124 | |||
125 | list_for_each_entry_safe(pt, next, &master->magicfree, head) { | ||
126 | list_del(&pt->head); | ||
127 | drm_ht_remove_item(&master->magiclist, &pt->hash_item); | ||
128 | drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC); | ||
129 | } | ||
130 | |||
131 | drm_ht_remove(&master->magiclist); | ||
132 | |||
133 | if (master->lock.hw_lock) { | ||
134 | if (dev->sigdata.lock == master->lock.hw_lock) | ||
135 | dev->sigdata.lock = NULL; | ||
136 | master->lock.hw_lock = NULL; | ||
137 | master->lock.file_priv = NULL; | ||
138 | wake_up_interruptible(&master->lock.lock_queue); | ||
139 | } | ||
140 | |||
141 | drm_free(master, sizeof(*master), DRM_MEM_DRIVER); | ||
142 | } | ||
143 | |||
144 | void drm_master_put(struct drm_master **master) | ||
145 | { | ||
146 | kref_put(&(*master)->refcount, drm_master_destroy); | ||
147 | *master = NULL; | ||
148 | } | ||
149 | |||
150 | int drm_setmaster_ioctl(struct drm_device *dev, void *data, | ||
151 | struct drm_file *file_priv) | ||
152 | { | ||
153 | if (file_priv->minor->master && file_priv->minor->master != file_priv->master) | ||
154 | return -EINVAL; | ||
155 | |||
156 | if (!file_priv->master) | ||
157 | return -EINVAL; | ||
158 | |||
159 | if (!file_priv->minor->master && | ||
160 | file_priv->minor->master != file_priv->master) { | ||
161 | mutex_lock(&dev->struct_mutex); | ||
162 | file_priv->minor->master = drm_master_get(file_priv->master); | ||
163 | mutex_lock(&dev->struct_mutex); | ||
164 | } | ||
165 | |||
166 | return 0; | ||
167 | } | ||
168 | |||
169 | int drm_dropmaster_ioctl(struct drm_device *dev, void *data, | ||
170 | struct drm_file *file_priv) | ||
171 | { | ||
172 | if (!file_priv->master) | ||
173 | return -EINVAL; | ||
174 | mutex_lock(&dev->struct_mutex); | ||
175 | drm_master_put(&file_priv->minor->master); | ||
176 | mutex_unlock(&dev->struct_mutex); | ||
177 | return 0; | ||
178 | } | ||
179 | |||
82 | static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev, | 180 | static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev, |
83 | const struct pci_device_id *ent, | 181 | const struct pci_device_id *ent, |
84 | struct drm_driver *driver) | 182 | struct drm_driver *driver) |
@@ -92,7 +190,6 @@ static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev, | |||
92 | 190 | ||
93 | spin_lock_init(&dev->count_lock); | 191 | spin_lock_init(&dev->count_lock); |
94 | spin_lock_init(&dev->drw_lock); | 192 | spin_lock_init(&dev->drw_lock); |
95 | spin_lock_init(&dev->lock.spinlock); | ||
96 | init_timer(&dev->timer); | 193 | init_timer(&dev->timer); |
97 | mutex_init(&dev->struct_mutex); | 194 | mutex_init(&dev->struct_mutex); |
98 | mutex_init(&dev->ctxlist_mutex); | 195 | mutex_init(&dev->ctxlist_mutex); |
@@ -200,6 +297,7 @@ static int drm_get_minor(struct drm_device *dev, struct drm_minor **minor, int t | |||
200 | new_minor->device = MKDEV(DRM_MAJOR, minor_id); | 297 | new_minor->device = MKDEV(DRM_MAJOR, minor_id); |
201 | new_minor->dev = dev; | 298 | new_minor->dev = dev; |
202 | new_minor->index = minor_id; | 299 | new_minor->index = minor_id; |
300 | INIT_LIST_HEAD(&new_minor->master_list); | ||
203 | 301 | ||
204 | idr_replace(&drm_minors_idr, new_minor, minor_id); | 302 | idr_replace(&drm_minors_idr, new_minor, minor_id); |
205 | 303 | ||
@@ -299,11 +397,6 @@ int drm_put_dev(struct drm_device * dev) | |||
299 | { | 397 | { |
300 | DRM_DEBUG("release primary %s\n", dev->driver->pci_driver.name); | 398 | DRM_DEBUG("release primary %s\n", dev->driver->pci_driver.name); |
301 | 399 | ||
302 | if (dev->unique) { | ||
303 | drm_free(dev->unique, strlen(dev->unique) + 1, DRM_MEM_DRIVER); | ||
304 | dev->unique = NULL; | ||
305 | dev->unique_len = 0; | ||
306 | } | ||
307 | if (dev->devname) { | 400 | if (dev->devname) { |
308 | drm_free(dev->devname, strlen(dev->devname) + 1, | 401 | drm_free(dev->devname, strlen(dev->devname) + 1, |
309 | DRM_MEM_DRIVER); | 402 | DRM_MEM_DRIVER); |