mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-24 21:24:00 +08:00
drm/nouveau/mc: handle irq-related setup ourselves
We need to be able to process interrupts before the DRM code is able to actually enable them, set it up ourselves. Also, it's less convoluted to *not* use the DRM wrappers it appears... Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
This commit is contained in:
parent
1a64634255
commit
0fa9061ae8
@ -213,7 +213,7 @@ nouveau-y += core/engine/vp/nve0.o
|
|||||||
|
|
||||||
# drm/core
|
# drm/core
|
||||||
nouveau-y += nouveau_drm.o nouveau_chan.o nouveau_dma.o nouveau_fence.o
|
nouveau-y += nouveau_drm.o nouveau_chan.o nouveau_dma.o nouveau_fence.o
|
||||||
nouveau-y += nouveau_irq.o nouveau_vga.o nouveau_agp.o
|
nouveau-y += nouveau_vga.o nouveau_agp.o
|
||||||
nouveau-y += nouveau_ttm.o nouveau_sgdma.o nouveau_bo.o nouveau_gem.o
|
nouveau-y += nouveau_ttm.o nouveau_sgdma.o nouveau_bo.o nouveau_gem.o
|
||||||
nouveau-y += nouveau_prime.o nouveau_abi16.o
|
nouveau-y += nouveau_prime.o nouveau_abi16.o
|
||||||
nouveau-y += nv04_fence.o nv10_fence.o nv17_fence.o
|
nouveau-y += nv04_fence.o nv10_fence.o nv17_fence.o
|
||||||
|
@ -21,18 +21,22 @@ nouveau_mc(void *obj)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define nouveau_mc_create(p,e,o,d) \
|
#define nouveau_mc_create(p,e,o,d) \
|
||||||
nouveau_subdev_create_((p), (e), (o), 0, "PMC", "master", \
|
nouveau_mc_create_((p), (e), (o), sizeof(**d), (void **)d)
|
||||||
sizeof(**d), (void **)d)
|
#define nouveau_mc_destroy(p) ({ \
|
||||||
#define nouveau_mc_destroy(p) \
|
struct nouveau_mc *pmc = (p); _nouveau_mc_dtor(nv_object(pmc)); \
|
||||||
nouveau_subdev_destroy(&(p)->base)
|
})
|
||||||
#define nouveau_mc_init(p) \
|
#define nouveau_mc_init(p) ({ \
|
||||||
nouveau_subdev_init(&(p)->base)
|
struct nouveau_mc *pmc = (p); _nouveau_mc_init(nv_object(pmc)); \
|
||||||
#define nouveau_mc_fini(p,s) \
|
})
|
||||||
nouveau_subdev_fini(&(p)->base, (s))
|
#define nouveau_mc_fini(p,s) ({ \
|
||||||
|
struct nouveau_mc *pmc = (p); _nouveau_mc_fini(nv_object(pmc), (s)); \
|
||||||
|
})
|
||||||
|
|
||||||
#define _nouveau_mc_dtor _nouveau_subdev_dtor
|
int nouveau_mc_create_(struct nouveau_object *, struct nouveau_object *,
|
||||||
#define _nouveau_mc_init _nouveau_subdev_init
|
struct nouveau_oclass *, int, void **);
|
||||||
#define _nouveau_mc_fini _nouveau_subdev_fini
|
void _nouveau_mc_dtor(struct nouveau_object *);
|
||||||
|
int _nouveau_mc_init(struct nouveau_object *);
|
||||||
|
int _nouveau_mc_fini(struct nouveau_object *, bool);
|
||||||
|
|
||||||
extern struct nouveau_oclass nv04_mc_oclass;
|
extern struct nouveau_oclass nv04_mc_oclass;
|
||||||
extern struct nouveau_oclass nv44_mc_oclass;
|
extern struct nouveau_oclass nv44_mc_oclass;
|
||||||
@ -40,8 +44,6 @@ extern struct nouveau_oclass nv50_mc_oclass;
|
|||||||
extern struct nouveau_oclass nv98_mc_oclass;
|
extern struct nouveau_oclass nv98_mc_oclass;
|
||||||
extern struct nouveau_oclass nvc0_mc_oclass;
|
extern struct nouveau_oclass nvc0_mc_oclass;
|
||||||
|
|
||||||
void nouveau_mc_intr(struct nouveau_subdev *);
|
|
||||||
|
|
||||||
extern const struct nouveau_mc_intr nv04_mc_intr[];
|
extern const struct nouveau_mc_intr nv04_mc_intr[];
|
||||||
int nv04_mc_init(struct nouveau_object *);
|
int nv04_mc_init(struct nouveau_object *);
|
||||||
int nv50_mc_init(struct nouveau_object *);
|
int nv50_mc_init(struct nouveau_object *);
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#include <linux/acpi.h>
|
#include <linux/acpi.h>
|
||||||
#include <linux/dmi.h>
|
#include <linux/dmi.h>
|
||||||
#include <linux/reboot.h>
|
#include <linux/reboot.h>
|
||||||
|
#include <linux/interrupt.h>
|
||||||
|
|
||||||
#include <asm/unaligned.h>
|
#include <asm/unaligned.h>
|
||||||
|
|
||||||
|
@ -24,10 +24,10 @@
|
|||||||
|
|
||||||
#include <subdev/mc.h>
|
#include <subdev/mc.h>
|
||||||
|
|
||||||
void
|
static irqreturn_t
|
||||||
nouveau_mc_intr(struct nouveau_subdev *subdev)
|
nouveau_mc_intr(int irq, void *arg)
|
||||||
{
|
{
|
||||||
struct nouveau_mc *pmc = nouveau_mc(subdev);
|
struct nouveau_mc *pmc = arg;
|
||||||
const struct nouveau_mc_intr *map = pmc->intr_map;
|
const struct nouveau_mc_intr *map = pmc->intr_map;
|
||||||
struct nouveau_subdev *unit;
|
struct nouveau_subdev *unit;
|
||||||
u32 stat, intr;
|
u32 stat, intr;
|
||||||
@ -35,7 +35,7 @@ nouveau_mc_intr(struct nouveau_subdev *subdev)
|
|||||||
intr = stat = nv_rd32(pmc, 0x000100);
|
intr = stat = nv_rd32(pmc, 0x000100);
|
||||||
while (stat && map->stat) {
|
while (stat && map->stat) {
|
||||||
if (stat & map->stat) {
|
if (stat & map->stat) {
|
||||||
unit = nouveau_subdev(subdev, map->unit);
|
unit = nouveau_subdev(pmc, map->unit);
|
||||||
if (unit && unit->intr)
|
if (unit && unit->intr)
|
||||||
unit->intr(unit);
|
unit->intr(unit);
|
||||||
intr &= ~map->stat;
|
intr &= ~map->stat;
|
||||||
@ -46,4 +46,56 @@ nouveau_mc_intr(struct nouveau_subdev *subdev)
|
|||||||
if (intr) {
|
if (intr) {
|
||||||
nv_error(pmc, "unknown intr 0x%08x\n", stat);
|
nv_error(pmc, "unknown intr 0x%08x\n", stat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return stat ? IRQ_HANDLED : IRQ_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
_nouveau_mc_fini(struct nouveau_object *object, bool suspend)
|
||||||
|
{
|
||||||
|
struct nouveau_mc *pmc = (void *)object;
|
||||||
|
nv_wr32(pmc, 0x000140, 0x00000000);
|
||||||
|
return nouveau_subdev_fini(&pmc->base, suspend);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
_nouveau_mc_init(struct nouveau_object *object)
|
||||||
|
{
|
||||||
|
struct nouveau_mc *pmc = (void *)object;
|
||||||
|
int ret = nouveau_subdev_init(&pmc->base);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
nv_wr32(pmc, 0x000140, 0x00000001);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_nouveau_mc_dtor(struct nouveau_object *object)
|
||||||
|
{
|
||||||
|
struct nouveau_device *device = nv_device(object);
|
||||||
|
struct nouveau_mc *pmc = (void *)object;
|
||||||
|
free_irq(device->pdev->irq, pmc);
|
||||||
|
nouveau_subdev_destroy(&pmc->base);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
nouveau_mc_create_(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||||
|
struct nouveau_oclass *oclass, int length, void **pobject)
|
||||||
|
{
|
||||||
|
struct nouveau_device *device = nv_device(parent);
|
||||||
|
struct nouveau_mc *pmc;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = nouveau_subdev_create_(parent, engine, oclass, 0, "PMC",
|
||||||
|
"master", length, pobject);
|
||||||
|
pmc = *pobject;
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = request_irq(device->pdev->irq, nouveau_mc_intr,
|
||||||
|
IRQF_SHARED, "nouveau", pmc);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,6 @@ nv04_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
nv_subdev(priv)->intr = nouveau_mc_intr;
|
|
||||||
priv->base.intr_map = nv04_mc_intr;
|
priv->base.intr_map = nv04_mc_intr;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,6 @@ nv44_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
nv_subdev(priv)->intr = nouveau_mc_intr;
|
|
||||||
priv->base.intr_map = nv04_mc_intr;
|
priv->base.intr_map = nv04_mc_intr;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,6 @@ nv50_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
nv_subdev(priv)->intr = nouveau_mc_intr;
|
|
||||||
priv->base.intr_map = nv50_mc_intr;
|
priv->base.intr_map = nv50_mc_intr;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -59,7 +59,6 @@ nv98_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
nv_subdev(priv)->intr = nouveau_mc_intr;
|
|
||||||
priv->base.intr_map = nv98_mc_intr;
|
priv->base.intr_map = nv98_mc_intr;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -61,7 +61,6 @@ nvc0_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
nv_subdev(priv)->intr = nouveau_mc_intr;
|
|
||||||
priv->base.intr_map = nvc0_mc_intr;
|
priv->base.intr_map = nvc0_mc_intr;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,6 @@
|
|||||||
#include <engine/disp.h>
|
#include <engine/disp.h>
|
||||||
|
|
||||||
#include "nouveau_drm.h"
|
#include "nouveau_drm.h"
|
||||||
#include "nouveau_irq.h"
|
|
||||||
#include "nouveau_dma.h"
|
#include "nouveau_dma.h"
|
||||||
#include "nouveau_ttm.h"
|
#include "nouveau_ttm.h"
|
||||||
#include "nouveau_gem.h"
|
#include "nouveau_gem.h"
|
||||||
@ -365,10 +364,6 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags)
|
|||||||
if (ret)
|
if (ret)
|
||||||
goto fail_bios;
|
goto fail_bios;
|
||||||
|
|
||||||
ret = nouveau_irq_init(dev);
|
|
||||||
if (ret)
|
|
||||||
goto fail_irq;
|
|
||||||
|
|
||||||
ret = nouveau_display_create(dev);
|
ret = nouveau_display_create(dev);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto fail_dispctor;
|
goto fail_dispctor;
|
||||||
@ -388,8 +383,6 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags)
|
|||||||
fail_dispinit:
|
fail_dispinit:
|
||||||
nouveau_display_destroy(dev);
|
nouveau_display_destroy(dev);
|
||||||
fail_dispctor:
|
fail_dispctor:
|
||||||
nouveau_irq_fini(dev);
|
|
||||||
fail_irq:
|
|
||||||
nouveau_bios_takedown(dev);
|
nouveau_bios_takedown(dev);
|
||||||
fail_bios:
|
fail_bios:
|
||||||
nouveau_ttm_fini(drm);
|
nouveau_ttm_fini(drm);
|
||||||
@ -415,7 +408,6 @@ nouveau_drm_unload(struct drm_device *dev)
|
|||||||
nouveau_display_fini(dev);
|
nouveau_display_fini(dev);
|
||||||
nouveau_display_destroy(dev);
|
nouveau_display_destroy(dev);
|
||||||
|
|
||||||
nouveau_irq_fini(dev);
|
|
||||||
nouveau_bios_takedown(dev);
|
nouveau_bios_takedown(dev);
|
||||||
|
|
||||||
nouveau_ttm_fini(drm);
|
nouveau_ttm_fini(drm);
|
||||||
@ -533,7 +525,6 @@ nouveau_do_resume(struct drm_device *dev)
|
|||||||
nouveau_fence(drm)->resume(drm);
|
nouveau_fence(drm)->resume(drm);
|
||||||
|
|
||||||
nouveau_run_vbios_init(dev);
|
nouveau_run_vbios_init(dev);
|
||||||
nouveau_irq_postinstall(dev);
|
|
||||||
nouveau_pm_resume(dev);
|
nouveau_pm_resume(dev);
|
||||||
|
|
||||||
if (dev->mode_config.num_crtc) {
|
if (dev->mode_config.num_crtc) {
|
||||||
@ -669,8 +660,7 @@ static struct drm_driver
|
|||||||
driver = {
|
driver = {
|
||||||
.driver_features =
|
.driver_features =
|
||||||
DRIVER_USE_AGP | DRIVER_PCI_DMA | DRIVER_SG |
|
DRIVER_USE_AGP | DRIVER_PCI_DMA | DRIVER_SG |
|
||||||
DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_GEM |
|
DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME,
|
||||||
DRIVER_MODESET | DRIVER_PRIME,
|
|
||||||
|
|
||||||
.load = nouveau_drm_load,
|
.load = nouveau_drm_load,
|
||||||
.unload = nouveau_drm_unload,
|
.unload = nouveau_drm_unload,
|
||||||
@ -684,11 +674,6 @@ driver = {
|
|||||||
.debugfs_cleanup = nouveau_debugfs_takedown,
|
.debugfs_cleanup = nouveau_debugfs_takedown,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
.irq_preinstall = nouveau_irq_preinstall,
|
|
||||||
.irq_postinstall = nouveau_irq_postinstall,
|
|
||||||
.irq_uninstall = nouveau_irq_uninstall,
|
|
||||||
.irq_handler = nouveau_irq_handler,
|
|
||||||
|
|
||||||
.get_vblank_counter = drm_vblank_count,
|
.get_vblank_counter = drm_vblank_count,
|
||||||
.enable_vblank = nouveau_drm_vblank_enable,
|
.enable_vblank = nouveau_drm_vblank_enable,
|
||||||
.disable_vblank = nouveau_drm_vblank_disable,
|
.disable_vblank = nouveau_drm_vblank_disable,
|
||||||
|
@ -1,76 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2012 Red Hat Inc.
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
* copy of this software and associated documentation files (the "Software"),
|
|
||||||
* to deal in the Software without restriction, including without limitation
|
|
||||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
* and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
* Software is furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
||||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
|
||||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
|
||||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
||||||
* OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
*
|
|
||||||
* Authors: Ben Skeggs
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <subdev/mc.h>
|
|
||||||
|
|
||||||
#include "nouveau_drm.h"
|
|
||||||
#include "nouveau_irq.h"
|
|
||||||
#include "nv50_display.h"
|
|
||||||
|
|
||||||
void
|
|
||||||
nouveau_irq_preinstall(struct drm_device *dev)
|
|
||||||
{
|
|
||||||
nv_wr32(nouveau_dev(dev), 0x000140, 0x00000000);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
nouveau_irq_postinstall(struct drm_device *dev)
|
|
||||||
{
|
|
||||||
nv_wr32(nouveau_dev(dev), 0x000140, 0x00000001);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
nouveau_irq_uninstall(struct drm_device *dev)
|
|
||||||
{
|
|
||||||
nv_wr32(nouveau_dev(dev), 0x000140, 0x00000000);
|
|
||||||
}
|
|
||||||
|
|
||||||
irqreturn_t
|
|
||||||
nouveau_irq_handler(DRM_IRQ_ARGS)
|
|
||||||
{
|
|
||||||
struct drm_device *dev = arg;
|
|
||||||
struct nouveau_device *device = nouveau_dev(dev);
|
|
||||||
struct nouveau_mc *pmc = nouveau_mc(device);
|
|
||||||
u32 stat;
|
|
||||||
|
|
||||||
stat = nv_rd32(device, 0x000100);
|
|
||||||
if (stat == 0 || stat == ~0)
|
|
||||||
return IRQ_NONE;
|
|
||||||
|
|
||||||
nv_subdev(pmc)->intr(nv_subdev(pmc));
|
|
||||||
return IRQ_HANDLED;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
nouveau_irq_init(struct drm_device *dev)
|
|
||||||
{
|
|
||||||
return drm_irq_install(dev);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
nouveau_irq_fini(struct drm_device *dev)
|
|
||||||
{
|
|
||||||
drm_irq_uninstall(dev);
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
#ifndef __NOUVEAU_IRQ_H__
|
|
||||||
#define __NOUVEAU_IRQ_H__
|
|
||||||
|
|
||||||
extern int nouveau_irq_init(struct drm_device *);
|
|
||||||
extern void nouveau_irq_fini(struct drm_device *);
|
|
||||||
extern irqreturn_t nouveau_irq_handler(DRM_IRQ_ARGS);
|
|
||||||
extern void nouveau_irq_preinstall(struct drm_device *);
|
|
||||||
extern int nouveau_irq_postinstall(struct drm_device *);
|
|
||||||
extern void nouveau_irq_uninstall(struct drm_device *);
|
|
||||||
|
|
||||||
#endif
|
|
Loading…
Reference in New Issue
Block a user