Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * drm_irq.c IRQ and vblank support
0003  *
0004  * \author Rickard E. (Rik) Faith <faith@valinux.com>
0005  * \author Gareth Hughes <gareth@valinux.com>
0006  *
0007  * Permission is hereby granted, free of charge, to any person obtaining a
0008  * copy of this software and associated documentation files (the "Software"),
0009  * to deal in the Software without restriction, including without limitation
0010  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0011  * and/or sell copies of the Software, and to permit persons to whom the
0012  * Software is furnished to do so, subject to the following conditions:
0013  *
0014  * The above copyright notice and this permission notice (including the next
0015  * paragraph) shall be included in all copies or substantial portions of the
0016  * Software.
0017  *
0018  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0019  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0020  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0021  * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
0022  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0023  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0024  * OTHER DEALINGS IN THE SOFTWARE.
0025  */
0026 
0027 /*
0028  * Created: Fri Mar 19 14:30:16 1999 by faith@valinux.com
0029  *
0030  * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
0031  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
0032  * All Rights Reserved.
0033  *
0034  * Permission is hereby granted, free of charge, to any person obtaining a
0035  * copy of this software and associated documentation files (the "Software"),
0036  * to deal in the Software without restriction, including without limitation
0037  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0038  * and/or sell copies of the Software, and to permit persons to whom the
0039  * Software is furnished to do so, subject to the following conditions:
0040  *
0041  * The above copyright notice and this permission notice (including the next
0042  * paragraph) shall be included in all copies or substantial portions of the
0043  * Software.
0044  *
0045  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0046  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0047  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0048  * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
0049  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0050  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0051  * OTHER DEALINGS IN THE SOFTWARE.
0052  */
0053 
0054 
0055 #include <linux/export.h>
0056 #include <linux/interrupt.h>    /* For task queue support */
0057 #include <linux/pci.h>
0058 #include <linux/vgaarb.h>
0059 
0060 #include <drm/drm.h>
0061 #include <drm/drm_device.h>
0062 #include <drm/drm_drv.h>
0063 #include <drm/drm_legacy.h>
0064 #include <drm/drm_print.h>
0065 #include <drm/drm_vblank.h>
0066 
0067 #include "drm_internal.h"
0068 
0069 static int drm_legacy_irq_install(struct drm_device *dev, int irq)
0070 {
0071     int ret;
0072     unsigned long sh_flags = 0;
0073 
0074     if (irq == 0)
0075         return -EINVAL;
0076 
0077     if (dev->irq_enabled)
0078         return -EBUSY;
0079     dev->irq_enabled = true;
0080 
0081     DRM_DEBUG("irq=%d\n", irq);
0082 
0083     /* Before installing handler */
0084     if (dev->driver->irq_preinstall)
0085         dev->driver->irq_preinstall(dev);
0086 
0087     /* PCI devices require shared interrupts. */
0088     if (dev_is_pci(dev->dev))
0089         sh_flags = IRQF_SHARED;
0090 
0091     ret = request_irq(irq, dev->driver->irq_handler,
0092               sh_flags, dev->driver->name, dev);
0093 
0094     if (ret < 0) {
0095         dev->irq_enabled = false;
0096         return ret;
0097     }
0098 
0099     /* After installing handler */
0100     if (dev->driver->irq_postinstall)
0101         ret = dev->driver->irq_postinstall(dev);
0102 
0103     if (ret < 0) {
0104         dev->irq_enabled = false;
0105         if (drm_core_check_feature(dev, DRIVER_LEGACY))
0106             vga_client_unregister(to_pci_dev(dev->dev));
0107         free_irq(irq, dev);
0108     } else {
0109         dev->irq = irq;
0110     }
0111 
0112     return ret;
0113 }
0114 
0115 int drm_legacy_irq_uninstall(struct drm_device *dev)
0116 {
0117     unsigned long irqflags;
0118     bool irq_enabled;
0119     int i;
0120 
0121     irq_enabled = dev->irq_enabled;
0122     dev->irq_enabled = false;
0123 
0124     /*
0125      * Wake up any waiters so they don't hang. This is just to paper over
0126      * issues for UMS drivers which aren't in full control of their
0127      * vblank/irq handling. KMS drivers must ensure that vblanks are all
0128      * disabled when uninstalling the irq handler.
0129      */
0130     if (drm_dev_has_vblank(dev)) {
0131         spin_lock_irqsave(&dev->vbl_lock, irqflags);
0132         for (i = 0; i < dev->num_crtcs; i++) {
0133             struct drm_vblank_crtc *vblank = &dev->vblank[i];
0134 
0135             if (!vblank->enabled)
0136                 continue;
0137 
0138             WARN_ON(drm_core_check_feature(dev, DRIVER_MODESET));
0139 
0140             drm_vblank_disable_and_save(dev, i);
0141             wake_up(&vblank->queue);
0142         }
0143         spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
0144     }
0145 
0146     if (!irq_enabled)
0147         return -EINVAL;
0148 
0149     DRM_DEBUG("irq=%d\n", dev->irq);
0150 
0151     if (drm_core_check_feature(dev, DRIVER_LEGACY))
0152         vga_client_unregister(to_pci_dev(dev->dev));
0153 
0154     if (dev->driver->irq_uninstall)
0155         dev->driver->irq_uninstall(dev);
0156 
0157     free_irq(dev->irq, dev);
0158 
0159     return 0;
0160 }
0161 EXPORT_SYMBOL(drm_legacy_irq_uninstall);
0162 
0163 int drm_legacy_irq_control(struct drm_device *dev, void *data,
0164                struct drm_file *file_priv)
0165 {
0166     struct drm_control *ctl = data;
0167     int ret = 0, irq;
0168     struct pci_dev *pdev;
0169 
0170     /* if we haven't irq we fallback for compatibility reasons -
0171      * this used to be a separate function in drm_dma.h
0172      */
0173 
0174     if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
0175         return 0;
0176     if (!drm_core_check_feature(dev, DRIVER_LEGACY))
0177         return 0;
0178     /* UMS was only ever supported on pci devices. */
0179     if (WARN_ON(!dev_is_pci(dev->dev)))
0180         return -EINVAL;
0181 
0182     switch (ctl->func) {
0183     case DRM_INST_HANDLER:
0184         pdev = to_pci_dev(dev->dev);
0185         irq = pdev->irq;
0186 
0187         if (dev->if_version < DRM_IF_VERSION(1, 2) &&
0188             ctl->irq != irq)
0189             return -EINVAL;
0190         mutex_lock(&dev->struct_mutex);
0191         ret = drm_legacy_irq_install(dev, irq);
0192         mutex_unlock(&dev->struct_mutex);
0193 
0194         return ret;
0195     case DRM_UNINST_HANDLER:
0196         mutex_lock(&dev->struct_mutex);
0197         ret = drm_legacy_irq_uninstall(dev);
0198         mutex_unlock(&dev->struct_mutex);
0199 
0200         return ret;
0201     default:
0202         return -EINVAL;
0203     }
0204 }