/** * IRQ control ioctl. * * \param inode device inode. * \param file_priv DRM file private. * \param cmd command. * \param arg user argument, pointing to a drm_control structure. * \return zero on success or a negative number on failure. * * Calls irq_install() or irq_uninstall() according to \p arg. */ int drm_control(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_control *ctl = data; /* Handle drivers who used to require IRQ setup no longer does. */ if (!(dev->driver->flags & DRIVER_IRQ)) return (0); switch (ctl->func) { case DRM_INST_HANDLER: if (drm_core_check_feature(dev, DRIVER_MODESET)) return 0; if (dev->if_version < DRM_IF_VERSION(1, 2) && ctl->irq != dev->irq) return (EINVAL); return (drm_irq_install(dev)); case DRM_UNINST_HANDLER: if (drm_core_check_feature(dev, DRIVER_MODESET)) return 0; return (drm_irq_uninstall(dev)); default: return (EINVAL); } }
/* * Setversion ioctl. * * \param inode device inode. * \param file_priv DRM file private. * \param cmd command. * \param arg user argument, pointing to a drm_lock structure. * \return zero on success or negative number on failure. * * Sets the requested interface version */ static int drm_setversion(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_set_version *sv = data; int if_version, retcode = 0; mutex_lock(&dev->master_mutex); if (sv->drm_di_major != -1) { if (sv->drm_di_major != DRM_IF_MAJOR || sv->drm_di_minor < 0 || sv->drm_di_minor > DRM_IF_MINOR) { retcode = -EINVAL; goto done; } if_version = DRM_IF_VERSION(sv->drm_di_major, sv->drm_di_minor); dev->if_version = max(if_version, dev->if_version); if (sv->drm_di_minor >= 1) { /* * Version 1.1 includes tying of DRM to specific device * Version 1.4 has proper PCI domain support */ retcode = drm_set_busid(dev, file_priv); if (retcode) goto done; } } if (sv->drm_dd_major != -1) { if (sv->drm_dd_major != dev->driver->major || sv->drm_dd_minor < 0 || sv->drm_dd_minor > dev->driver->minor) { retcode = -EINVAL; goto done; } } done: sv->drm_di_major = DRM_IF_MAJOR; sv->drm_di_minor = DRM_IF_MINOR; sv->drm_dd_major = dev->driver->major; sv->drm_dd_minor = dev->driver->minor; mutex_unlock(&dev->master_mutex); return retcode; }
int drm_legacy_irq_control(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_control *ctl = data; int ret = 0, irq; /* if we haven't irq we fallback for compatibility reasons - * this used to be a separate function in drm_dma.h */ if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) return 0; if (!drm_core_check_feature(dev, DRIVER_LEGACY)) return 0; /* UMS was only ever supported on pci devices. */ if (WARN_ON(!dev->pdev)) return -EINVAL; switch (ctl->func) { case DRM_INST_HANDLER: irq = dev->pdev->irq; if (dev->if_version < DRM_IF_VERSION(1, 2) && ctl->irq != irq) return -EINVAL; mutex_lock(&dev->struct_mutex); ret = drm_irq_install(dev, irq); mutex_unlock(&dev->struct_mutex); return ret; case DRM_UNINST_HANDLER: mutex_lock(&dev->struct_mutex); ret = drm_irq_uninstall(dev); mutex_unlock(&dev->struct_mutex); return ret; default: return -EINVAL; } }