diff options
-rw-r--r-- | lib/core/os.h | 11 | ||||
-rw-r--r-- | nvkm/include/subdev/mc.h | 1 | ||||
-rw-r--r-- | nvkm/subdev/mc/base.c | 23 |
3 files changed, 35 insertions, 0 deletions
diff --git a/lib/core/os.h b/lib/core/os.h index 76a75d231..1e90357cf 100644 --- a/lib/core/os.h +++ b/lib/core/os.h @@ -555,6 +555,17 @@ pci_free_consistent(struct pci_dev *hwdev, size_t size, { } +static inline int +pci_enable_msi(struct pci_dev *pdev) +{ + return -ENOSYS; +} + +static inline void +pci_disable_msi(struct pci_dev *pdev) +{ +} + #define PCI_DEVFN(a,b) 0 #define pci_get_bus_and_slot(a, b) NULL #define pci_read_config_dword(a,b,c) *(c) = 0 diff --git a/nvkm/include/subdev/mc.h b/nvkm/include/subdev/mc.h index 9d2cd2006..ce6569f36 100644 --- a/nvkm/include/subdev/mc.h +++ b/nvkm/include/subdev/mc.h @@ -12,6 +12,7 @@ struct nouveau_mc_intr { struct nouveau_mc { struct nouveau_subdev base; const struct nouveau_mc_intr *intr_map; + bool use_msi; }; static inline struct nouveau_mc * 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) |