Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a27e5699 authored by Lucas Stach's avatar Lucas Stach Committed by Ben Skeggs
Browse files

drm/nouveau: use MSI interrupts



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: default avatarLucas Stach <dev@lynxeye.de>
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 4b31ebcf
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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 *
+1 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#include <linux/reboot.h>
#include <linux/interrupt.h>
#include <linux/log2.h>
#include <linux/pm_runtime.h>

#include <asm/unaligned.h>

+23 −1
Original line number Diff line number Diff line
@@ -23,7 +23,7 @@
 */

#include <subdev/mc.h>
#include <linux/pm_runtime.h>
#include <core/option.h>

static irqreturn_t
nouveau_mc_intr(int irq, void *arg)
@@ -47,6 +47,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);
	}
@@ -81,6 +84,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);
}

@@ -102,6 +107,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)