Path: blob/master/drivers/gpu/drm/nouveau/nouveau_irq.c
15112 views
/*1* Copyright (C) 2006 Ben Skeggs.2*3* All Rights Reserved.4*5* Permission is hereby granted, free of charge, to any person obtaining6* a copy of this software and associated documentation files (the7* "Software"), to deal in the Software without restriction, including8* without limitation the rights to use, copy, modify, merge, publish,9* distribute, sublicense, and/or sell copies of the Software, and to10* permit persons to whom the Software is furnished to do so, subject to11* the following conditions:12*13* The above copyright notice and this permission notice (including the14* next paragraph) shall be included in all copies or substantial15* portions of the Software.16*17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,18* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF19* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.20* IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE21* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION22* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION23* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.24*25*/2627/*28* Authors:29* Ben Skeggs <[email protected]>30*/3132#include "drmP.h"33#include "drm.h"34#include "nouveau_drm.h"35#include "nouveau_drv.h"36#include "nouveau_reg.h"37#include "nouveau_ramht.h"38#include "nouveau_util.h"3940void41nouveau_irq_preinstall(struct drm_device *dev)42{43struct drm_nouveau_private *dev_priv = dev->dev_private;4445/* Master disable */46nv_wr32(dev, NV03_PMC_INTR_EN_0, 0);4748INIT_LIST_HEAD(&dev_priv->vbl_waiting);49}5051int52nouveau_irq_postinstall(struct drm_device *dev)53{54struct drm_nouveau_private *dev_priv = dev->dev_private;5556/* Master enable */57nv_wr32(dev, NV03_PMC_INTR_EN_0, NV_PMC_INTR_EN_0_MASTER_ENABLE);58if (dev_priv->msi_enabled)59nv_wr08(dev, 0x00088068, 0xff);6061return 0;62}6364void65nouveau_irq_uninstall(struct drm_device *dev)66{67/* Master disable */68nv_wr32(dev, NV03_PMC_INTR_EN_0, 0);69}7071irqreturn_t72nouveau_irq_handler(DRM_IRQ_ARGS)73{74struct drm_device *dev = (struct drm_device *)arg;75struct drm_nouveau_private *dev_priv = dev->dev_private;76unsigned long flags;77u32 stat;78int i;7980stat = nv_rd32(dev, NV03_PMC_INTR_0);81if (!stat)82return IRQ_NONE;8384spin_lock_irqsave(&dev_priv->context_switch_lock, flags);85for (i = 0; i < 32 && stat; i++) {86if (!(stat & (1 << i)) || !dev_priv->irq_handler[i])87continue;8889dev_priv->irq_handler[i](dev);90stat &= ~(1 << i);91}9293if (dev_priv->msi_enabled)94nv_wr08(dev, 0x00088068, 0xff);95spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);9697if (stat && nouveau_ratelimit())98NV_ERROR(dev, "PMC - unhandled INTR 0x%08x\n", stat);99return IRQ_HANDLED;100}101102int103nouveau_irq_init(struct drm_device *dev)104{105struct drm_nouveau_private *dev_priv = dev->dev_private;106int ret;107108if (nouveau_msi != 0 && dev_priv->card_type >= NV_50) {109ret = pci_enable_msi(dev->pdev);110if (ret == 0) {111NV_INFO(dev, "enabled MSI\n");112dev_priv->msi_enabled = true;113}114}115116return drm_irq_install(dev);117}118119void120nouveau_irq_fini(struct drm_device *dev)121{122struct drm_nouveau_private *dev_priv = dev->dev_private;123124drm_irq_uninstall(dev);125if (dev_priv->msi_enabled)126pci_disable_msi(dev->pdev);127}128129void130nouveau_irq_register(struct drm_device *dev, int status_bit,131void (*handler)(struct drm_device *))132{133struct drm_nouveau_private *dev_priv = dev->dev_private;134unsigned long flags;135136spin_lock_irqsave(&dev_priv->context_switch_lock, flags);137dev_priv->irq_handler[status_bit] = handler;138spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);139}140141void142nouveau_irq_unregister(struct drm_device *dev, int status_bit)143{144struct drm_nouveau_private *dev_priv = dev->dev_private;145unsigned long flags;146147spin_lock_irqsave(&dev_priv->context_switch_lock, flags);148dev_priv->irq_handler[status_bit] = NULL;149spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);150}151152153