cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

drm_irq.c (6022B)


      1/*
      2 * drm_irq.c IRQ and vblank support
      3 *
      4 * \author Rickard E. (Rik) Faith <faith@valinux.com>
      5 * \author Gareth Hughes <gareth@valinux.com>
      6 *
      7 * Permission is hereby granted, free of charge, to any person obtaining a
      8 * copy of this software and associated documentation files (the "Software"),
      9 * to deal in the Software without restriction, including without limitation
     10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     11 * and/or sell copies of the Software, and to permit persons to whom the
     12 * Software is furnished to do so, subject to the following conditions:
     13 *
     14 * The above copyright notice and this permission notice (including the next
     15 * paragraph) shall be included in all copies or substantial portions of the
     16 * Software.
     17 *
     18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     21 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
     22 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     23 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     24 * OTHER DEALINGS IN THE SOFTWARE.
     25 */
     26
     27/*
     28 * Created: Fri Mar 19 14:30:16 1999 by faith@valinux.com
     29 *
     30 * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
     31 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
     32 * All Rights Reserved.
     33 *
     34 * Permission is hereby granted, free of charge, to any person obtaining a
     35 * copy of this software and associated documentation files (the "Software"),
     36 * to deal in the Software without restriction, including without limitation
     37 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     38 * and/or sell copies of the Software, and to permit persons to whom the
     39 * Software is furnished to do so, subject to the following conditions:
     40 *
     41 * The above copyright notice and this permission notice (including the next
     42 * paragraph) shall be included in all copies or substantial portions of the
     43 * Software.
     44 *
     45 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     46 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     47 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     48 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
     49 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     50 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     51 * OTHER DEALINGS IN THE SOFTWARE.
     52 */
     53
     54
     55#include <linux/export.h>
     56#include <linux/interrupt.h>	/* For task queue support */
     57#include <linux/pci.h>
     58#include <linux/vgaarb.h>
     59
     60#include <drm/drm.h>
     61#include <drm/drm_device.h>
     62#include <drm/drm_drv.h>
     63#include <drm/drm_legacy.h>
     64#include <drm/drm_print.h>
     65#include <drm/drm_vblank.h>
     66
     67#include "drm_internal.h"
     68
     69static int drm_legacy_irq_install(struct drm_device *dev, int irq)
     70{
     71	int ret;
     72	unsigned long sh_flags = 0;
     73
     74	if (irq == 0)
     75		return -EINVAL;
     76
     77	if (dev->irq_enabled)
     78		return -EBUSY;
     79	dev->irq_enabled = true;
     80
     81	DRM_DEBUG("irq=%d\n", irq);
     82
     83	/* Before installing handler */
     84	if (dev->driver->irq_preinstall)
     85		dev->driver->irq_preinstall(dev);
     86
     87	/* PCI devices require shared interrupts. */
     88	if (dev_is_pci(dev->dev))
     89		sh_flags = IRQF_SHARED;
     90
     91	ret = request_irq(irq, dev->driver->irq_handler,
     92			  sh_flags, dev->driver->name, dev);
     93
     94	if (ret < 0) {
     95		dev->irq_enabled = false;
     96		return ret;
     97	}
     98
     99	/* After installing handler */
    100	if (dev->driver->irq_postinstall)
    101		ret = dev->driver->irq_postinstall(dev);
    102
    103	if (ret < 0) {
    104		dev->irq_enabled = false;
    105		if (drm_core_check_feature(dev, DRIVER_LEGACY))
    106			vga_client_unregister(to_pci_dev(dev->dev));
    107		free_irq(irq, dev);
    108	} else {
    109		dev->irq = irq;
    110	}
    111
    112	return ret;
    113}
    114
    115int drm_legacy_irq_uninstall(struct drm_device *dev)
    116{
    117	unsigned long irqflags;
    118	bool irq_enabled;
    119	int i;
    120
    121	irq_enabled = dev->irq_enabled;
    122	dev->irq_enabled = false;
    123
    124	/*
    125	 * Wake up any waiters so they don't hang. This is just to paper over
    126	 * issues for UMS drivers which aren't in full control of their
    127	 * vblank/irq handling. KMS drivers must ensure that vblanks are all
    128	 * disabled when uninstalling the irq handler.
    129	 */
    130	if (drm_dev_has_vblank(dev)) {
    131		spin_lock_irqsave(&dev->vbl_lock, irqflags);
    132		for (i = 0; i < dev->num_crtcs; i++) {
    133			struct drm_vblank_crtc *vblank = &dev->vblank[i];
    134
    135			if (!vblank->enabled)
    136				continue;
    137
    138			WARN_ON(drm_core_check_feature(dev, DRIVER_MODESET));
    139
    140			drm_vblank_disable_and_save(dev, i);
    141			wake_up(&vblank->queue);
    142		}
    143		spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
    144	}
    145
    146	if (!irq_enabled)
    147		return -EINVAL;
    148
    149	DRM_DEBUG("irq=%d\n", dev->irq);
    150
    151	if (drm_core_check_feature(dev, DRIVER_LEGACY))
    152		vga_client_unregister(to_pci_dev(dev->dev));
    153
    154	if (dev->driver->irq_uninstall)
    155		dev->driver->irq_uninstall(dev);
    156
    157	free_irq(dev->irq, dev);
    158
    159	return 0;
    160}
    161EXPORT_SYMBOL(drm_legacy_irq_uninstall);
    162
    163int drm_legacy_irq_control(struct drm_device *dev, void *data,
    164			   struct drm_file *file_priv)
    165{
    166	struct drm_control *ctl = data;
    167	int ret = 0, irq;
    168	struct pci_dev *pdev;
    169
    170	/* if we haven't irq we fallback for compatibility reasons -
    171	 * this used to be a separate function in drm_dma.h
    172	 */
    173
    174	if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
    175		return 0;
    176	if (!drm_core_check_feature(dev, DRIVER_LEGACY))
    177		return 0;
    178	/* UMS was only ever supported on pci devices. */
    179	if (WARN_ON(!dev_is_pci(dev->dev)))
    180		return -EINVAL;
    181
    182	switch (ctl->func) {
    183	case DRM_INST_HANDLER:
    184		pdev = to_pci_dev(dev->dev);
    185		irq = pdev->irq;
    186
    187		if (dev->if_version < DRM_IF_VERSION(1, 2) &&
    188		    ctl->irq != irq)
    189			return -EINVAL;
    190		mutex_lock(&dev->struct_mutex);
    191		ret = drm_legacy_irq_install(dev, irq);
    192		mutex_unlock(&dev->struct_mutex);
    193
    194		return ret;
    195	case DRM_UNINST_HANDLER:
    196		mutex_lock(&dev->struct_mutex);
    197		ret = drm_legacy_irq_uninstall(dev);
    198		mutex_unlock(&dev->struct_mutex);
    199
    200		return ret;
    201	default:
    202		return -EINVAL;
    203	}
    204}