aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/drm/drm_irq.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/drm/drm_irq.c')
-rw-r--r--drivers/char/drm/drm_irq.c98
1 files changed, 40 insertions, 58 deletions
diff --git a/drivers/char/drm/drm_irq.c b/drivers/char/drm/drm_irq.c
index 871d2fde09b3..05eae63f85ba 100644
--- a/drivers/char/drm/drm_irq.c
+++ b/drivers/char/drm/drm_irq.c
@@ -41,7 +41,7 @@
41 * Get interrupt from bus id. 41 * Get interrupt from bus id.
42 * 42 *
43 * \param inode device inode. 43 * \param inode device inode.
44 * \param filp file pointer. 44 * \param file_priv DRM file private.
45 * \param cmd command. 45 * \param cmd command.
46 * \param arg user argument, pointing to a drm_irq_busid structure. 46 * \param arg user argument, pointing to a drm_irq_busid structure.
47 * \return zero on success or a negative number on failure. 47 * \return zero on success or a negative number on failure.
@@ -50,30 +50,24 @@
50 * This IOCTL is deprecated, and will now return EINVAL for any busid not equal 50 * This IOCTL is deprecated, and will now return EINVAL for any busid not equal
51 * to that of the device that this DRM instance attached to. 51 * to that of the device that this DRM instance attached to.
52 */ 52 */
53int drm_irq_by_busid(struct inode *inode, struct file *filp, 53int drm_irq_by_busid(struct drm_device *dev, void *data,
54 unsigned int cmd, unsigned long arg) 54 struct drm_file *file_priv)
55{ 55{
56 struct drm_file *priv = filp->private_data; 56 struct drm_irq_busid *p = data;
57 struct drm_device *dev = priv->head->dev;
58 struct drm_irq_busid __user *argp = (void __user *)arg;
59 struct drm_irq_busid p;
60 57
61 if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) 58 if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
62 return -EINVAL; 59 return -EINVAL;
63 60
64 if (copy_from_user(&p, argp, sizeof(p))) 61 if ((p->busnum >> 8) != drm_get_pci_domain(dev) ||
65 return -EFAULT; 62 (p->busnum & 0xff) != dev->pdev->bus->number ||
66 63 p->devnum != PCI_SLOT(dev->pdev->devfn) || p->funcnum != PCI_FUNC(dev->pdev->devfn))
67 if ((p.busnum >> 8) != drm_get_pci_domain(dev) ||
68 (p.busnum & 0xff) != dev->pdev->bus->number ||
69 p.devnum != PCI_SLOT(dev->pdev->devfn) || p.funcnum != PCI_FUNC(dev->pdev->devfn))
70 return -EINVAL; 64 return -EINVAL;
71 65
72 p.irq = dev->irq; 66 p->irq = dev->irq;
67
68 DRM_DEBUG("%d:%d:%d => IRQ %d\n", p->busnum, p->devnum, p->funcnum,
69 p->irq);
73 70
74 DRM_DEBUG("%d:%d:%d => IRQ %d\n", p.busnum, p.devnum, p.funcnum, p.irq);
75 if (copy_to_user(argp, &p, sizeof(p)))
76 return -EFAULT;
77 return 0; 71 return 0;
78} 72}
79 73
@@ -187,31 +181,27 @@ EXPORT_SYMBOL(drm_irq_uninstall);
187 * IRQ control ioctl. 181 * IRQ control ioctl.
188 * 182 *
189 * \param inode device inode. 183 * \param inode device inode.
190 * \param filp file pointer. 184 * \param file_priv DRM file private.
191 * \param cmd command. 185 * \param cmd command.
192 * \param arg user argument, pointing to a drm_control structure. 186 * \param arg user argument, pointing to a drm_control structure.
193 * \return zero on success or a negative number on failure. 187 * \return zero on success or a negative number on failure.
194 * 188 *
195 * Calls irq_install() or irq_uninstall() according to \p arg. 189 * Calls irq_install() or irq_uninstall() according to \p arg.
196 */ 190 */
197int drm_control(struct inode *inode, struct file *filp, 191int drm_control(struct drm_device *dev, void *data,
198 unsigned int cmd, unsigned long arg) 192 struct drm_file *file_priv)
199{ 193{
200 struct drm_file *priv = filp->private_data; 194 struct drm_control *ctl = data;
201 struct drm_device *dev = priv->head->dev;
202 struct drm_control ctl;
203 195
204 /* if we haven't irq we fallback for compatibility reasons - this used to be a separate function in drm_dma.h */ 196 /* if we haven't irq we fallback for compatibility reasons - this used to be a separate function in drm_dma.h */
205 197
206 if (copy_from_user(&ctl, (struct drm_control __user *) arg, sizeof(ctl)))
207 return -EFAULT;
208 198
209 switch (ctl.func) { 199 switch (ctl->func) {
210 case DRM_INST_HANDLER: 200 case DRM_INST_HANDLER:
211 if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) 201 if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
212 return 0; 202 return 0;
213 if (dev->if_version < DRM_IF_VERSION(1, 2) && 203 if (dev->if_version < DRM_IF_VERSION(1, 2) &&
214 ctl.irq != dev->irq) 204 ctl->irq != dev->irq)
215 return -EINVAL; 205 return -EINVAL;
216 return drm_irq_install(dev); 206 return drm_irq_install(dev);
217 case DRM_UNINST_HANDLER: 207 case DRM_UNINST_HANDLER:
@@ -227,7 +217,7 @@ int drm_control(struct inode *inode, struct file *filp,
227 * Wait for VBLANK. 217 * Wait for VBLANK.
228 * 218 *
229 * \param inode device inode. 219 * \param inode device inode.
230 * \param filp file pointer. 220 * \param file_priv DRM file private.
231 * \param cmd command. 221 * \param cmd command.
232 * \param data user argument, pointing to a drm_wait_vblank structure. 222 * \param data user argument, pointing to a drm_wait_vblank structure.
233 * \return zero on success or a negative number on failure. 223 * \return zero on success or a negative number on failure.
@@ -242,31 +232,25 @@ int drm_control(struct inode *inode, struct file *filp,
242 * 232 *
243 * If a signal is not requested, then calls vblank_wait(). 233 * If a signal is not requested, then calls vblank_wait().
244 */ 234 */
245int drm_wait_vblank(DRM_IOCTL_ARGS) 235int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_priv)
246{ 236{
247 struct drm_file *priv = filp->private_data; 237 union drm_wait_vblank *vblwait = data;
248 struct drm_device *dev = priv->head->dev;
249 union drm_wait_vblank __user *argp = (void __user *)data;
250 union drm_wait_vblank vblwait;
251 struct timeval now; 238 struct timeval now;
252 int ret = 0; 239 int ret = 0;
253 unsigned int flags, seq; 240 unsigned int flags, seq;
254 241
255 if (!dev->irq) 242 if ((!dev->irq) || (!dev->irq_enabled))
256 return -EINVAL; 243 return -EINVAL;
257 244
258 if (copy_from_user(&vblwait, argp, sizeof(vblwait))) 245 if (vblwait->request.type &
259 return -EFAULT;
260
261 if (vblwait.request.type &
262 ~(_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK)) { 246 ~(_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK)) {
263 DRM_ERROR("Unsupported type value 0x%x, supported mask 0x%x\n", 247 DRM_ERROR("Unsupported type value 0x%x, supported mask 0x%x\n",
264 vblwait.request.type, 248 vblwait->request.type,
265 (_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK)); 249 (_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK));
266 return -EINVAL; 250 return -EINVAL;
267 } 251 }
268 252
269 flags = vblwait.request.type & _DRM_VBLANK_FLAGS_MASK; 253 flags = vblwait->request.type & _DRM_VBLANK_FLAGS_MASK;
270 254
271 if (!drm_core_check_feature(dev, (flags & _DRM_VBLANK_SECONDARY) ? 255 if (!drm_core_check_feature(dev, (flags & _DRM_VBLANK_SECONDARY) ?
272 DRIVER_IRQ_VBL2 : DRIVER_IRQ_VBL)) 256 DRIVER_IRQ_VBL2 : DRIVER_IRQ_VBL))
@@ -275,10 +259,10 @@ int drm_wait_vblank(DRM_IOCTL_ARGS)
275 seq = atomic_read((flags & _DRM_VBLANK_SECONDARY) ? &dev->vbl_received2 259 seq = atomic_read((flags & _DRM_VBLANK_SECONDARY) ? &dev->vbl_received2
276 : &dev->vbl_received); 260 : &dev->vbl_received);
277 261
278 switch (vblwait.request.type & _DRM_VBLANK_TYPES_MASK) { 262 switch (vblwait->request.type & _DRM_VBLANK_TYPES_MASK) {
279 case _DRM_VBLANK_RELATIVE: 263 case _DRM_VBLANK_RELATIVE:
280 vblwait.request.sequence += seq; 264 vblwait->request.sequence += seq;
281 vblwait.request.type &= ~_DRM_VBLANK_RELATIVE; 265 vblwait->request.type &= ~_DRM_VBLANK_RELATIVE;
282 case _DRM_VBLANK_ABSOLUTE: 266 case _DRM_VBLANK_ABSOLUTE:
283 break; 267 break;
284 default: 268 default:
@@ -286,8 +270,8 @@ int drm_wait_vblank(DRM_IOCTL_ARGS)
286 } 270 }
287 271
288 if ((flags & _DRM_VBLANK_NEXTONMISS) && 272 if ((flags & _DRM_VBLANK_NEXTONMISS) &&
289 (seq - vblwait.request.sequence) <= (1<<23)) { 273 (seq - vblwait->request.sequence) <= (1<<23)) {
290 vblwait.request.sequence = seq + 1; 274 vblwait->request.sequence = seq + 1;
291 } 275 }
292 276
293 if (flags & _DRM_VBLANK_SIGNAL) { 277 if (flags & _DRM_VBLANK_SIGNAL) {
@@ -303,12 +287,13 @@ int drm_wait_vblank(DRM_IOCTL_ARGS)
303 * that case 287 * that case
304 */ 288 */
305 list_for_each_entry(vbl_sig, vbl_sigs, head) { 289 list_for_each_entry(vbl_sig, vbl_sigs, head) {
306 if (vbl_sig->sequence == vblwait.request.sequence 290 if (vbl_sig->sequence == vblwait->request.sequence
307 && vbl_sig->info.si_signo == vblwait.request.signal 291 && vbl_sig->info.si_signo ==
292 vblwait->request.signal
308 && vbl_sig->task == current) { 293 && vbl_sig->task == current) {
309 spin_unlock_irqrestore(&dev->vbl_lock, 294 spin_unlock_irqrestore(&dev->vbl_lock,
310 irqflags); 295 irqflags);
311 vblwait.reply.sequence = seq; 296 vblwait->reply.sequence = seq;
312 goto done; 297 goto done;
313 } 298 }
314 } 299 }
@@ -330,8 +315,8 @@ int drm_wait_vblank(DRM_IOCTL_ARGS)
330 315
331 memset((void *)vbl_sig, 0, sizeof(*vbl_sig)); 316 memset((void *)vbl_sig, 0, sizeof(*vbl_sig));
332 317
333 vbl_sig->sequence = vblwait.request.sequence; 318 vbl_sig->sequence = vblwait->request.sequence;
334 vbl_sig->info.si_signo = vblwait.request.signal; 319 vbl_sig->info.si_signo = vblwait->request.signal;
335 vbl_sig->task = current; 320 vbl_sig->task = current;
336 321
337 spin_lock_irqsave(&dev->vbl_lock, irqflags); 322 spin_lock_irqsave(&dev->vbl_lock, irqflags);
@@ -340,25 +325,22 @@ int drm_wait_vblank(DRM_IOCTL_ARGS)
340 325
341 spin_unlock_irqrestore(&dev->vbl_lock, irqflags); 326 spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
342 327
343 vblwait.reply.sequence = seq; 328 vblwait->reply.sequence = seq;
344 } else { 329 } else {
345 if (flags & _DRM_VBLANK_SECONDARY) { 330 if (flags & _DRM_VBLANK_SECONDARY) {
346 if (dev->driver->vblank_wait2) 331 if (dev->driver->vblank_wait2)
347 ret = dev->driver->vblank_wait2(dev, &vblwait.request.sequence); 332 ret = dev->driver->vblank_wait2(dev, &vblwait->request.sequence);
348 } else if (dev->driver->vblank_wait) 333 } else if (dev->driver->vblank_wait)
349 ret = 334 ret =
350 dev->driver->vblank_wait(dev, 335 dev->driver->vblank_wait(dev,
351 &vblwait.request.sequence); 336 &vblwait->request.sequence);
352 337
353 do_gettimeofday(&now); 338 do_gettimeofday(&now);
354 vblwait.reply.tval_sec = now.tv_sec; 339 vblwait->reply.tval_sec = now.tv_sec;
355 vblwait.reply.tval_usec = now.tv_usec; 340 vblwait->reply.tval_usec = now.tv_usec;
356 } 341 }
357 342
358 done: 343 done:
359 if (copy_to_user(argp, &vblwait, sizeof(vblwait)))
360 return -EFAULT;
361
362 return ret; 344 return ret;
363} 345}
364 346