diff options
author | Lucas Stach <dev@lynxeye.de> | 2013-08-28 02:00:50 +0200 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2013-09-17 08:18:04 +1000 |
commit | 9f4306bda87496b50fbd610a213280380d0bb190 (patch) | |
tree | c69044acb23376b1b5f711ed983718bff076c8cd /nvkm/subdev/mc | |
parent | 3af07077deef3c4ba681e1a29c2133cfeec2ba78 (diff) | |
download | nouveau-9f4306bda87496b50fbd610a213280380d0bb190.tar.gz |
mc: use MSI interrupts where possible
MSIs were only problematic on some old, broken chipsets. But now that we
already see systems where PCI legacy interrupts are somewhat flaky, it's
really time to move to MSIs.
v2 (Ben Skeggs): blacklist BR02 boards
Signed-off-by: Lucas Stach <dev@lynxeye.de>
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'nvkm/subdev/mc')
-rw-r--r-- | nvkm/subdev/mc/base.c | 23 |
1 files changed, 23 insertions, 0 deletions
diff --git a/nvkm/subdev/mc/base.c b/nvkm/subdev/mc/base.c index ec9cd6f10..92fbf6405 100644 --- a/nvkm/subdev/mc/base.c +++ b/nvkm/subdev/mc/base.c @@ -23,6 +23,7 @@ */ #include <subdev/mc.h> +#include <core/option.h> static irqreturn_t nouveau_mc_intr(int irq, void *arg) @@ -43,6 +44,9 @@ nouveau_mc_intr(int irq, void *arg) map++; } + if (pmc->use_msi) + nv_wr08(pmc->base.base.parent, 0x00088068, 0xff); + if (intr) { nv_error(pmc, "unknown intr 0x%08x\n", stat); } @@ -75,6 +79,8 @@ _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); + if (pmc->use_msi) + pci_disable_msi(device->pdev); nouveau_subdev_destroy(&pmc->base); } @@ -96,6 +102,23 @@ nouveau_mc_create_(struct nouveau_object *parent, struct nouveau_object *engine, pmc->intr_map = intr_map; + switch (device->pdev->device & 0x0ff0) { + case 0x00f0: /* BR02? */ + case 0x02e0: /* BR02? */ + pmc->use_msi = false; + break; + default: + pmc->use_msi = nouveau_boolopt(device->cfgopt, "NvMSI", true); + if (pmc->use_msi) { + pmc->use_msi = pci_enable_msi(device->pdev) == 0; + if (pmc->use_msi) { + nv_info(pmc, "MSI interrupts enabled\n"); + nv_wr08(device, 0x00088068, 0xff); + } + } + break; + } + ret = request_irq(device->pdev->irq, nouveau_mc_intr, IRQF_SHARED, "nouveau", pmc); if (ret < 0) |