Browse Source

drm/nouveau/mc: move device irq handling to platform-specific code

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Ben Skeggs 10 years ago
parent
commit
2b700825e7

+ 1 - 3
drivers/gpu/drm/nouveau/include/nvkm/core/device.h

@@ -146,6 +146,7 @@ struct nvkm_device_func {
 	struct nvkm_device_tegra *(*tegra)(struct nvkm_device *);
 	void *(*dtor)(struct nvkm_device *);
 	int (*preinit)(struct nvkm_device *);
+	int (*init)(struct nvkm_device *);
 	void (*fini)(struct nvkm_device *, bool suspend);
 };
 
@@ -247,9 +248,6 @@ nv_device_resource_start(struct nvkm_device *device, unsigned int bar);
 resource_size_t
 nv_device_resource_len(struct nvkm_device *device, unsigned int bar);
 
-int
-nv_device_get_irq(struct nvkm_device *device, bool stall);
-
 struct platform_device;
 
 enum nv_bus_type {

+ 1 - 0
drivers/gpu/drm/nouveau/include/nvkm/core/tegra.h

@@ -5,6 +5,7 @@
 struct nvkm_device_tegra {
 	struct nvkm_device device;
 	struct platform_device *pdev;
+	int irq;
 };
 
 int nvkm_device_tegra_new(struct platform_device *,

+ 1 - 8
drivers/gpu/drm/nouveau/include/nvkm/subdev/mc.h

@@ -5,24 +5,17 @@
 struct nvkm_mc {
 	const struct nvkm_mc_func *func;
 	struct nvkm_subdev subdev;
-
-	unsigned int irq;
-	bool use_msi;
 };
 
+void nvkm_mc_intr(struct nvkm_mc *, bool *handled);
 void nvkm_mc_intr_unarm(struct nvkm_mc *);
 void nvkm_mc_intr_rearm(struct nvkm_mc *);
-u32 nvkm_mc_intr_mask(struct nvkm_mc *);
 void nvkm_mc_unk260(struct nvkm_mc *, u32 data);
 
 int nv04_mc_new(struct nvkm_device *, int, struct nvkm_mc **);
-int nv40_mc_new(struct nvkm_device *, int, struct nvkm_mc **);
 int nv44_mc_new(struct nvkm_device *, int, struct nvkm_mc **);
-int nv4c_mc_new(struct nvkm_device *, int, struct nvkm_mc **);
 int nv50_mc_new(struct nvkm_device *, int, struct nvkm_mc **);
-int g94_mc_new(struct nvkm_device *, int, struct nvkm_mc **);
 int g98_mc_new(struct nvkm_device *, int, struct nvkm_mc **);
 int gf100_mc_new(struct nvkm_device *, int, struct nvkm_mc **);
-int gf106_mc_new(struct nvkm_device *, int, struct nvkm_mc **);
 int gk20a_mc_new(struct nvkm_device *, int, struct nvkm_mc **);
 #endif

+ 3 - 1
drivers/gpu/drm/nouveau/include/nvkm/subdev/pci.h

@@ -5,13 +5,15 @@
 struct nvkm_pci {
 	const struct nvkm_pci_func *func;
 	struct nvkm_subdev subdev;
+	struct pci_dev *pdev;
+	int irq;
+	bool msi;
 };
 
 u32 nvkm_pci_rd32(struct nvkm_pci *, u16 addr);
 void nvkm_pci_wr08(struct nvkm_pci *, u16 addr, u8 data);
 void nvkm_pci_wr32(struct nvkm_pci *, u16 addr, u32 data);
 void nvkm_pci_rom_shadow(struct nvkm_pci *, bool shadow);
-void nvkm_pci_msi_rearm(struct nvkm_pci *);
 
 int nv04_pci_new(struct nvkm_device *, int, struct nvkm_pci **);
 int nv40_pci_new(struct nvkm_device *, int, struct nvkm_pci **);

+ 34 - 38
drivers/gpu/drm/nouveau/nvkm/engine/device/base.c

@@ -479,7 +479,7 @@ nv40_chipset = {
 	.gpio = nv10_gpio_new,
 	.i2c = nv04_i2c_new,
 	.imem = nv40_instmem_new,
-	.mc = nv40_mc_new,
+	.mc = nv04_mc_new,
 	.mmu = nv04_mmu_new,
 	.pci = nv40_pci_new,
 	.therm = nv40_therm_new,
@@ -505,7 +505,7 @@ nv41_chipset = {
 	.gpio = nv10_gpio_new,
 	.i2c = nv04_i2c_new,
 	.imem = nv40_instmem_new,
-	.mc = nv40_mc_new,
+	.mc = nv04_mc_new,
 	.mmu = nv41_mmu_new,
 	.pci = nv40_pci_new,
 	.therm = nv40_therm_new,
@@ -531,7 +531,7 @@ nv42_chipset = {
 	.gpio = nv10_gpio_new,
 	.i2c = nv04_i2c_new,
 	.imem = nv40_instmem_new,
-	.mc = nv40_mc_new,
+	.mc = nv04_mc_new,
 	.mmu = nv41_mmu_new,
 	.pci = nv40_pci_new,
 	.therm = nv40_therm_new,
@@ -557,7 +557,7 @@ nv43_chipset = {
 	.gpio = nv10_gpio_new,
 	.i2c = nv04_i2c_new,
 	.imem = nv40_instmem_new,
-	.mc = nv40_mc_new,
+	.mc = nv04_mc_new,
 	.mmu = nv41_mmu_new,
 	.pci = nv40_pci_new,
 	.therm = nv40_therm_new,
@@ -609,7 +609,7 @@ nv45_chipset = {
 	.gpio = nv10_gpio_new,
 	.i2c = nv04_i2c_new,
 	.imem = nv40_instmem_new,
-	.mc = nv40_mc_new,
+	.mc = nv04_mc_new,
 	.mmu = nv04_mmu_new,
 	.pci = nv40_pci_new,
 	.therm = nv40_therm_new,
@@ -661,7 +661,7 @@ nv47_chipset = {
 	.gpio = nv10_gpio_new,
 	.i2c = nv04_i2c_new,
 	.imem = nv40_instmem_new,
-	.mc = nv40_mc_new,
+	.mc = nv04_mc_new,
 	.mmu = nv41_mmu_new,
 	.pci = nv40_pci_new,
 	.therm = nv40_therm_new,
@@ -687,7 +687,7 @@ nv49_chipset = {
 	.gpio = nv10_gpio_new,
 	.i2c = nv04_i2c_new,
 	.imem = nv40_instmem_new,
-	.mc = nv40_mc_new,
+	.mc = nv04_mc_new,
 	.mmu = nv41_mmu_new,
 	.pci = nv40_pci_new,
 	.therm = nv40_therm_new,
@@ -739,7 +739,7 @@ nv4b_chipset = {
 	.gpio = nv10_gpio_new,
 	.i2c = nv04_i2c_new,
 	.imem = nv40_instmem_new,
-	.mc = nv40_mc_new,
+	.mc = nv04_mc_new,
 	.mmu = nv41_mmu_new,
 	.pci = nv40_pci_new,
 	.therm = nv40_therm_new,
@@ -765,7 +765,7 @@ nv4c_chipset = {
 	.gpio = nv10_gpio_new,
 	.i2c = nv04_i2c_new,
 	.imem = nv40_instmem_new,
-	.mc = nv4c_mc_new,
+	.mc = nv44_mc_new,
 	.mmu = nv44_mmu_new,
 	.pci = nv4c_pci_new,
 	.therm = nv40_therm_new,
@@ -791,7 +791,7 @@ nv4e_chipset = {
 	.gpio = nv10_gpio_new,
 	.i2c = nv4e_i2c_new,
 	.imem = nv40_instmem_new,
-	.mc = nv4c_mc_new,
+	.mc = nv44_mc_new,
 	.mmu = nv44_mmu_new,
 	.pci = nv4c_pci_new,
 	.therm = nv40_therm_new,
@@ -846,7 +846,7 @@ nv63_chipset = {
 	.gpio = nv10_gpio_new,
 	.i2c = nv04_i2c_new,
 	.imem = nv40_instmem_new,
-	.mc = nv4c_mc_new,
+	.mc = nv44_mc_new,
 	.mmu = nv44_mmu_new,
 	.pci = nv4c_pci_new,
 	.therm = nv40_therm_new,
@@ -872,7 +872,7 @@ nv67_chipset = {
 	.gpio = nv10_gpio_new,
 	.i2c = nv04_i2c_new,
 	.imem = nv40_instmem_new,
-	.mc = nv4c_mc_new,
+	.mc = nv44_mc_new,
 	.mmu = nv44_mmu_new,
 	.pci = nv4c_pci_new,
 	.therm = nv40_therm_new,
@@ -898,7 +898,7 @@ nv68_chipset = {
 	.gpio = nv10_gpio_new,
 	.i2c = nv04_i2c_new,
 	.imem = nv40_instmem_new,
-	.mc = nv4c_mc_new,
+	.mc = nv44_mc_new,
 	.mmu = nv44_mmu_new,
 	.pci = nv4c_pci_new,
 	.therm = nv40_therm_new,
@@ -1022,7 +1022,7 @@ nv94_chipset = {
 	.gpio = g94_gpio_new,
 	.i2c = g94_i2c_new,
 	.imem = nv50_instmem_new,
-	.mc = g94_mc_new,
+	.mc = nv50_mc_new,
 	.mmu = nv50_mmu_new,
 	.mxm = nv50_mxm_new,
 	.pci = nv40_pci_new,
@@ -1054,7 +1054,7 @@ nv96_chipset = {
 	.gpio = g94_gpio_new,
 	.i2c = g94_i2c_new,
 	.imem = nv50_instmem_new,
-	.mc = g94_mc_new,
+	.mc = nv50_mc_new,
 	.mmu = nv50_mmu_new,
 	.mxm = nv50_mxm_new,
 	.pci = nv40_pci_new,
@@ -1385,7 +1385,7 @@ nvc1_chipset = {
 	.ibus = gf100_ibus_new,
 	.imem = nv50_instmem_new,
 	.ltc = gf100_ltc_new,
-	.mc = gf106_mc_new,
+	.mc = gf100_mc_new,
 	.mmu = gf100_mmu_new,
 	.mxm = nv50_mxm_new,
 	.pci = nv40_pci_new,
@@ -1420,7 +1420,7 @@ nvc3_chipset = {
 	.ibus = gf100_ibus_new,
 	.imem = nv50_instmem_new,
 	.ltc = gf100_ltc_new,
-	.mc = gf106_mc_new,
+	.mc = gf100_mc_new,
 	.mmu = gf100_mmu_new,
 	.mxm = nv50_mxm_new,
 	.pci = nv40_pci_new,
@@ -1563,7 +1563,7 @@ nvcf_chipset = {
 	.ibus = gf100_ibus_new,
 	.imem = nv50_instmem_new,
 	.ltc = gf100_ltc_new,
-	.mc = gf106_mc_new,
+	.mc = gf100_mc_new,
 	.mmu = gf100_mmu_new,
 	.mxm = nv50_mxm_new,
 	.pci = nv40_pci_new,
@@ -1598,7 +1598,7 @@ nvd7_chipset = {
 	.ibus = gf100_ibus_new,
 	.imem = nv50_instmem_new,
 	.ltc = gf100_ltc_new,
-	.mc = gf106_mc_new,
+	.mc = gf100_mc_new,
 	.mmu = gf100_mmu_new,
 	.mxm = nv50_mxm_new,
 	.pci = nv40_pci_new,
@@ -1631,7 +1631,7 @@ nvd9_chipset = {
 	.ibus = gf100_ibus_new,
 	.imem = nv50_instmem_new,
 	.ltc = gf100_ltc_new,
-	.mc = gf106_mc_new,
+	.mc = gf100_mc_new,
 	.mmu = gf100_mmu_new,
 	.mxm = nv50_mxm_new,
 	.pci = nv40_pci_new,
@@ -1666,7 +1666,7 @@ nve4_chipset = {
 	.ibus = gk104_ibus_new,
 	.imem = nv50_instmem_new,
 	.ltc = gk104_ltc_new,
-	.mc = gf106_mc_new,
+	.mc = gf100_mc_new,
 	.mmu = gf100_mmu_new,
 	.mxm = nv50_mxm_new,
 	.pci = nv40_pci_new,
@@ -1703,7 +1703,7 @@ nve6_chipset = {
 	.ibus = gk104_ibus_new,
 	.imem = nv50_instmem_new,
 	.ltc = gk104_ltc_new,
-	.mc = gf106_mc_new,
+	.mc = gf100_mc_new,
 	.mmu = gf100_mmu_new,
 	.mxm = nv50_mxm_new,
 	.pci = nv40_pci_new,
@@ -1740,7 +1740,7 @@ nve7_chipset = {
 	.ibus = gk104_ibus_new,
 	.imem = nv50_instmem_new,
 	.ltc = gk104_ltc_new,
-	.mc = gf106_mc_new,
+	.mc = gf100_mc_new,
 	.mmu = gf100_mmu_new,
 	.mxm = nv50_mxm_new,
 	.pci = nv40_pci_new,
@@ -1801,7 +1801,7 @@ nvf0_chipset = {
 	.ibus = gk104_ibus_new,
 	.imem = nv50_instmem_new,
 	.ltc = gk104_ltc_new,
-	.mc = gf106_mc_new,
+	.mc = gf100_mc_new,
 	.mmu = gf100_mmu_new,
 	.mxm = nv50_mxm_new,
 	.pci = nv40_pci_new,
@@ -1837,7 +1837,7 @@ nvf1_chipset = {
 	.ibus = gk104_ibus_new,
 	.imem = nv50_instmem_new,
 	.ltc = gk104_ltc_new,
-	.mc = gf106_mc_new,
+	.mc = gf100_mc_new,
 	.mmu = gf100_mmu_new,
 	.mxm = nv50_mxm_new,
 	.pci = nv40_pci_new,
@@ -2231,11 +2231,17 @@ nvkm_device_init(struct nvkm_device *device)
 	nvdev_trace(device, "init running...\n");
 	time = ktime_to_us(ktime_get());
 
+	if (device->func->init) {
+		ret = device->func->init(device);
+		if (ret)
+			goto fail;
+	}
+
 	for (i = 0; i < NVKM_SUBDEV_NR; i++) {
 		if ((subdev = nvkm_device_subdev(device, i))) {
 			ret = nvkm_subdev_init(subdev);
 			if (ret)
-				goto fail;
+				goto fail_subdev;
 		}
 	}
 
@@ -2245,12 +2251,13 @@ nvkm_device_init(struct nvkm_device *device)
 	nvdev_trace(device, "init completed in %lldus\n", time);
 	return 0;
 
-fail:
+fail_subdev:
 	do {
 		if ((subdev = nvkm_device_subdev(device, i)))
 			nvkm_subdev_fini(subdev, false);
 	} while (--i >= 0);
 
+fail:
 	nvdev_error(device, "init failed with %d\n", ret);
 	return ret;
 }
@@ -2285,17 +2292,6 @@ nv_device_resource_len(struct nvkm_device *device, unsigned int bar)
 	}
 }
 
-int
-nv_device_get_irq(struct nvkm_device *device, bool stall)
-{
-	if (nv_device_is_pci(device)) {
-		return device->pdev->irq;
-	} else {
-		return platform_get_irq_byname(device->platformdev,
-					       stall ? "stall" : "nonstall");
-	}
-}
-
 void
 nvkm_device_del(struct nvkm_device **pdevice)
 {

+ 46 - 0
drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c

@@ -31,9 +31,54 @@ nvkm_device_tegra(struct nvkm_device *obj)
 	return container_of(obj, struct nvkm_device_tegra, device);
 }
 
+static irqreturn_t
+nvkm_device_tegra_intr(int irq, void *arg)
+{
+	struct nvkm_device_tegra *tdev = arg;
+	struct nvkm_mc *mc = tdev->device.mc;
+	bool handled = false;
+	if (likely(mc)) {
+		nvkm_mc_intr_unarm(mc);
+		nvkm_mc_intr(mc, &handled);
+		nvkm_mc_intr_rearm(mc);
+	}
+	return handled ? IRQ_HANDLED : IRQ_NONE;
+}
+
+static void
+nvkm_device_tegra_fini(struct nvkm_device *device, bool suspend)
+{
+	struct nvkm_device_tegra *tdev = nvkm_device_tegra(device);
+	if (tdev->irq) {
+		free_irq(tdev->irq, tdev);
+		tdev->irq = 0;
+	};
+}
+
+static int
+nvkm_device_tegra_init(struct nvkm_device *device)
+{
+	struct nvkm_device_tegra *tdev = nvkm_device_tegra(device);
+	int irq, ret;
+
+	irq = platform_get_irq_byname(tdev->pdev, "stall");
+	if (irq < 0)
+		return irq;
+
+	ret = request_irq(irq, nvkm_device_tegra_intr,
+			  IRQF_SHARED, "nvkm", tdev);
+	if (ret)
+		return ret;
+
+	tdev->irq = irq;
+	return 0;
+}
+
 static const struct nvkm_device_func
 nvkm_device_tegra_func = {
 	.tegra = nvkm_device_tegra,
+	.init = nvkm_device_tegra_init,
+	.fini = nvkm_device_tegra_fini,
 };
 
 int
@@ -48,6 +93,7 @@ nvkm_device_tegra_new(struct platform_device *pdev,
 		return -ENOMEM;
 	*pdevice = &tdev->device;
 	tdev->pdev = pdev;
+	tdev->irq = -1;
 
 	return nvkm_device_ctor(&nvkm_device_tegra_func, NULL, pdev,
 				NVKM_BUS_PLATFORM, pdev->id, NULL,

+ 0 - 4
drivers/gpu/drm/nouveau/nvkm/subdev/mc/Kbuild

@@ -1,11 +1,7 @@
 nvkm-y += nvkm/subdev/mc/base.o
 nvkm-y += nvkm/subdev/mc/nv04.o
-nvkm-y += nvkm/subdev/mc/nv40.o
 nvkm-y += nvkm/subdev/mc/nv44.o
-nvkm-y += nvkm/subdev/mc/nv4c.o
 nvkm-y += nvkm/subdev/mc/nv50.o
-nvkm-y += nvkm/subdev/mc/g94.o
 nvkm-y += nvkm/subdev/mc/g98.o
 nvkm-y += nvkm/subdev/mc/gf100.o
-nvkm-y += nvkm/subdev/mc/gf106.o
 nvkm-y += nvkm/subdev/mc/gk20a.o

+ 19 - 80
drivers/gpu/drm/nouveau/nvkm/subdev/mc/base.c

@@ -44,7 +44,7 @@ nvkm_mc_intr_rearm(struct nvkm_mc *mc)
 	return mc->func->intr_rearm(mc);
 }
 
-u32
+static u32
 nvkm_mc_intr_mask(struct nvkm_mc *mc)
 {
 	u32 intr = mc->func->intr_mask(mc);
@@ -53,39 +53,28 @@ nvkm_mc_intr_mask(struct nvkm_mc *mc)
 	return intr;
 }
 
-static irqreturn_t
-nvkm_mc_intr(int irq, void *arg)
+void
+nvkm_mc_intr(struct nvkm_mc *mc, bool *handled)
 {
-	struct nvkm_mc *mc = arg;
-	struct nvkm_subdev *subdev = &mc->subdev;
-	struct nvkm_device *device = subdev->device;
+	struct nvkm_device *device = mc->subdev.device;
+	struct nvkm_subdev *subdev;
 	const struct nvkm_mc_intr *map = mc->func->intr;
-	struct nvkm_subdev *unit;
-	u32 intr;
-
-	nvkm_mc_intr_unarm(mc);
-	intr = nvkm_mc_intr_mask(mc);
-	if (mc->use_msi)
-		mc->func->msi_rearm(mc);
-
-	if (intr) {
-		u32 stat = intr = nvkm_mc_intr_mask(mc);
-		while (map->stat) {
-			if (intr & map->stat) {
-				unit = nvkm_device_subdev(device, map->unit);
-				if (unit)
-					nvkm_subdev_intr(unit);
-				stat &= ~map->stat;
-			}
-			map++;
+	u32 stat, intr;
+
+	stat = intr = nvkm_mc_intr_mask(mc);
+	while (map->stat) {
+		if (intr & map->stat) {
+			subdev = nvkm_device_subdev(device, map->unit);
+			if (subdev)
+				nvkm_subdev_intr(subdev);
+			stat &= ~map->stat;
 		}
-
-		if (stat)
-			nvkm_error(subdev, "unknown intr %08x\n", stat);
+		map++;
 	}
 
-	nvkm_mc_intr_rearm(mc);
-	return intr ? IRQ_HANDLED : IRQ_NONE;
+	if (stat)
+		nvkm_error(&mc->subdev, "intr %08x\n", stat);
+	*handled = intr != 0;
 }
 
 static int
@@ -96,13 +85,6 @@ nvkm_mc_fini(struct nvkm_subdev *subdev, bool suspend)
 	return 0;
 }
 
-static int
-nvkm_mc_oneinit(struct nvkm_subdev *subdev)
-{
-	struct nvkm_mc *mc = nvkm_mc(subdev);
-	return request_irq(mc->irq, nvkm_mc_intr, IRQF_SHARED, "nvkm", mc);
-}
-
 static int
 nvkm_mc_init(struct nvkm_subdev *subdev)
 {
@@ -116,18 +98,12 @@ nvkm_mc_init(struct nvkm_subdev *subdev)
 static void *
 nvkm_mc_dtor(struct nvkm_subdev *subdev)
 {
-	struct nvkm_mc *mc = nvkm_mc(subdev);
-	struct nvkm_device *device = mc->subdev.device;
-	free_irq(mc->irq, mc);
-	if (mc->use_msi)
-		pci_disable_msi(device->pdev);
-	return mc;
+	return nvkm_mc(subdev);
 }
 
 static const struct nvkm_subdev_func
 nvkm_mc = {
 	.dtor = nvkm_mc_dtor,
-	.oneinit = nvkm_mc_oneinit,
 	.init = nvkm_mc_init,
 	.fini = nvkm_mc_fini,
 };
@@ -137,48 +113,11 @@ nvkm_mc_new_(const struct nvkm_mc_func *func, struct nvkm_device *device,
 	     int index, struct nvkm_mc **pmc)
 {
 	struct nvkm_mc *mc;
-	int ret;
 
 	if (!(mc = *pmc = kzalloc(sizeof(*mc), GFP_KERNEL)))
 		return -ENOMEM;
 
 	nvkm_subdev_ctor(&nvkm_mc, device, index, 0, &mc->subdev);
 	mc->func = func;
-
-	if (nv_device_is_pci(device)) {
-		switch (device->pdev->device & 0x0ff0) {
-		case 0x00f0:
-		case 0x02e0:
-			/* BR02? NFI how these would be handled yet exactly */
-			break;
-		default:
-			switch (device->chipset) {
-			case 0xaa:
-				/* reported broken, nv also disable it */
-				break;
-			default:
-				mc->use_msi = true;
-				break;
-			}
-		}
-
-		mc->use_msi = nvkm_boolopt(device->cfgopt, "NvMSI",
-					    mc->use_msi);
-
-		if (mc->use_msi && mc->func->msi_rearm) {
-			mc->use_msi = pci_enable_msi(device->pdev) == 0;
-			if (mc->use_msi) {
-				nvkm_debug(&mc->subdev, "MSI enabled\n");
-				mc->func->msi_rearm(mc);
-			}
-		} else {
-			mc->use_msi = false;
-		}
-	}
-
-	ret = nv_device_get_irq(device, true);
-	if (ret < 0)
-		return ret;
-	mc->irq = ret;
 	return 0;
 }

+ 0 - 40
drivers/gpu/drm/nouveau/nvkm/subdev/mc/g94.c

@@ -1,40 +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 "priv.h"
-
-static const struct nvkm_mc_func
-g94_mc = {
-	.init = nv50_mc_init,
-	.intr = nv50_mc_intr,
-	.intr_unarm = nv04_mc_intr_unarm,
-	.intr_rearm = nv04_mc_intr_rearm,
-	.intr_mask = nv04_mc_intr_mask,
-	.msi_rearm = nv40_mc_msi_rearm,
-};
-
-int
-g94_mc_new(struct nvkm_device *device, int index, struct nvkm_mc **pmc)
-{
-	return nvkm_mc_new_(&g94_mc, device, index, pmc);
-}

+ 0 - 1
drivers/gpu/drm/nouveau/nvkm/subdev/mc/g98.c

@@ -51,7 +51,6 @@ g98_mc = {
 	.intr_unarm = nv04_mc_intr_unarm,
 	.intr_rearm = nv04_mc_intr_rearm,
 	.intr_mask = nv04_mc_intr_mask,
-	.msi_rearm = nv40_mc_msi_rearm,
 };
 
 int

+ 0 - 7
drivers/gpu/drm/nouveau/nvkm/subdev/mc/gf100.c

@@ -74,12 +74,6 @@ gf100_mc_intr_mask(struct nvkm_mc *mc)
 	return intr0 | intr1;
 }
 
-static void
-gf100_mc_msi_rearm(struct nvkm_mc *mc)
-{
-	nvkm_wr32(mc->subdev.device, 0x088704, 0x00000000);
-}
-
 void
 gf100_mc_unk260(struct nvkm_mc *mc, u32 data)
 {
@@ -93,7 +87,6 @@ gf100_mc = {
 	.intr_unarm = gf100_mc_intr_unarm,
 	.intr_rearm = gf100_mc_intr_rearm,
 	.intr_mask = gf100_mc_intr_mask,
-	.msi_rearm = gf100_mc_msi_rearm,
 	.unk260 = gf100_mc_unk260,
 };
 

+ 0 - 41
drivers/gpu/drm/nouveau/nvkm/subdev/mc/gf106.c

@@ -1,41 +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 "priv.h"
-
-static const struct nvkm_mc_func
-gf106_mc = {
-	.init = nv50_mc_init,
-	.intr = gf100_mc_intr,
-	.intr_unarm = gf100_mc_intr_unarm,
-	.intr_rearm = gf100_mc_intr_rearm,
-	.intr_mask = gf100_mc_intr_mask,
-	.msi_rearm = nv40_mc_msi_rearm,
-	.unk260 = gf100_mc_unk260,
-};
-
-int
-gf106_mc_new(struct nvkm_device *device, int index, struct nvkm_mc **pmc)
-{
-	return nvkm_mc_new_(&gf106_mc, device, index, pmc);
-}

+ 0 - 1
drivers/gpu/drm/nouveau/nvkm/subdev/mc/gk20a.c

@@ -30,7 +30,6 @@ gk20a_mc = {
 	.intr_unarm = gf100_mc_intr_unarm,
 	.intr_rearm = gf100_mc_intr_rearm,
 	.intr_mask = gf100_mc_intr_mask,
-	.msi_rearm = nv40_mc_msi_rearm,
 };
 
 int

+ 0 - 46
drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv40.c

@@ -1,46 +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 "priv.h"
-
-void
-nv40_mc_msi_rearm(struct nvkm_mc *mc)
-{
-	nvkm_wr08(mc->subdev.device, 0x088068, 0xff);
-}
-
-static const struct nvkm_mc_func
-nv40_mc = {
-	.init = nv04_mc_init,
-	.intr = nv04_mc_intr,
-	.intr_unarm = nv04_mc_intr_unarm,
-	.intr_rearm = nv04_mc_intr_rearm,
-	.intr_mask = nv04_mc_intr_mask,
-	.msi_rearm = nv40_mc_msi_rearm,
-};
-
-int
-nv40_mc_new(struct nvkm_device *device, int index, struct nvkm_mc **pmc)
-{
-	return nvkm_mc_new_(&nv40_mc, device, index, pmc);
-}

+ 0 - 1
drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv44.c

@@ -44,7 +44,6 @@ nv44_mc = {
 	.intr_unarm = nv04_mc_intr_unarm,
 	.intr_rearm = nv04_mc_intr_rearm,
 	.intr_mask = nv04_mc_intr_mask,
-	.msi_rearm = nv40_mc_msi_rearm,
 };
 
 int

+ 0 - 39
drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv4c.c

@@ -1,39 +0,0 @@
-/*
- * Copyright 2014 Ilia Mirkin
- *
- * 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: Ilia Mirkin
- */
-#include "priv.h"
-
-static const struct nvkm_mc_func
-nv4c_mc = {
-	.init = nv44_mc_init,
-	.intr = nv04_mc_intr,
-	.intr_unarm = nv04_mc_intr_unarm,
-	.intr_rearm = nv04_mc_intr_rearm,
-	.intr_mask = nv04_mc_intr_mask,
-};
-
-int
-nv4c_mc_new(struct nvkm_device *device, int index, struct nvkm_mc **pmc)
-{
-	return nvkm_mc_new_(&nv4c_mc, device, index, pmc);
-}

+ 0 - 8
drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv50.c

@@ -41,13 +41,6 @@ nv50_mc_intr[] = {
 	{},
 };
 
-static void
-nv50_mc_msi_rearm(struct nvkm_mc *mc)
-{
-	struct nvkm_device *device = mc->subdev.device;
-	pci_write_config_byte(device->pdev, 0x68, 0xff);
-}
-
 void
 nv50_mc_init(struct nvkm_mc *mc)
 {
@@ -62,7 +55,6 @@ nv50_mc = {
 	.intr_unarm = nv04_mc_intr_unarm,
 	.intr_rearm = nv04_mc_intr_rearm,
 	.intr_mask = nv04_mc_intr_mask,
-	.msi_rearm = nv50_mc_msi_rearm,
 };
 
 int

+ 0 - 3
drivers/gpu/drm/nouveau/nvkm/subdev/mc/priv.h

@@ -20,7 +20,6 @@ struct nvkm_mc_func {
 	void (*intr_rearm)(struct nvkm_mc *);
 	/* retrieve pending interrupt mask (NV_PMC_INTR) */
 	u32 (*intr_mask)(struct nvkm_mc *);
-	void (*msi_rearm)(struct nvkm_mc *);
 	void (*unk260)(struct nvkm_mc *, u32);
 };
 
@@ -30,8 +29,6 @@ void nv04_mc_intr_unarm(struct nvkm_mc *);
 void nv04_mc_intr_rearm(struct nvkm_mc *);
 u32 nv04_mc_intr_mask(struct nvkm_mc *);
 
-void nv40_mc_msi_rearm(struct nvkm_mc *);
-
 void nv44_mc_init(struct nvkm_mc *);
 
 void nv50_mc_init(struct nvkm_mc *);

+ 77 - 3
drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c

@@ -23,6 +23,10 @@
  */
 #include "priv.h"
 
+#include <core/option.h>
+#include <core/pci.h>
+#include <subdev/mc.h>
+
 u32
 nvkm_pci_rd32(struct nvkm_pci *pci, u16 addr)
 {
@@ -52,21 +56,62 @@ nvkm_pci_rom_shadow(struct nvkm_pci *pci, bool shadow)
 	nvkm_pci_wr32(pci, 0x0050, data);
 }
 
-void
-nvkm_pci_msi_rearm(struct nvkm_pci *pci)
+static irqreturn_t
+nvkm_pci_intr(int irq, void *arg)
+{
+	struct nvkm_pci *pci = arg;
+	struct nvkm_mc *mc = pci->subdev.device->mc;
+	bool handled = false;
+	if (likely(mc)) {
+		nvkm_mc_intr_unarm(mc);
+		if (pci->msi)
+			pci->func->msi_rearm(pci);
+		nvkm_mc_intr(mc, &handled);
+		nvkm_mc_intr_rearm(mc);
+	}
+	return handled ? IRQ_HANDLED : IRQ_NONE;
+}
+
+static int
+nvkm_pci_fini(struct nvkm_subdev *subdev, bool suspend)
 {
-	pci->func->msi_rearm(pci);
+	struct nvkm_pci *pci = nvkm_pci(subdev);
+	if (pci->irq >= 0) {
+		free_irq(pci->irq, pci);
+		pci->irq = -1;
+	};
+	return 0;
+}
+
+static int
+nvkm_pci_init(struct nvkm_subdev *subdev)
+{
+	struct nvkm_pci *pci = nvkm_pci(subdev);
+	struct pci_dev *pdev = pci->pdev;
+	int ret;
+
+	ret = request_irq(pdev->irq, nvkm_pci_intr, IRQF_SHARED, "nvkm", pci);
+	if (ret)
+		return ret;
+
+	pci->irq = pdev->irq;
+	return ret;
 }
 
 static void *
 nvkm_pci_dtor(struct nvkm_subdev *subdev)
 {
+	struct nvkm_pci *pci = nvkm_pci(subdev);
+	if (pci->msi)
+		pci_disable_msi(pci->pdev);
 	return nvkm_pci(subdev);
 }
 
 static const struct nvkm_subdev_func
 nvkm_pci_func = {
 	.dtor = nvkm_pci_dtor,
+	.init = nvkm_pci_init,
+	.fini = nvkm_pci_fini,
 };
 
 int
@@ -74,9 +119,38 @@ nvkm_pci_new_(const struct nvkm_pci_func *func, struct nvkm_device *device,
 	      int index, struct nvkm_pci **ppci)
 {
 	struct nvkm_pci *pci;
+
 	if (!(pci = *ppci = kzalloc(sizeof(**ppci), GFP_KERNEL)))
 		return -ENOMEM;
 	nvkm_subdev_ctor(&nvkm_pci_func, device, index, 0, &pci->subdev);
 	pci->func = func;
+	pci->pdev = device->func->pci(device)->pdev;
+	pci->irq = -1;
+
+	switch (pci->pdev->device & 0x0ff0) {
+	case 0x00f0:
+	case 0x02e0:
+		/* BR02? NFI how these would be handled yet exactly */
+		break;
+	default:
+		switch (device->chipset) {
+		case 0xaa:
+			/* reported broken, nv also disable it */
+			break;
+		default:
+			pci->msi = true;
+			break;
+		}
+	}
+
+	pci->msi = nvkm_boolopt(device->cfgopt, "NvMSI", pci->msi);
+	if (pci->msi && func->msi_rearm) {
+		pci->msi = pci_enable_msi(pci->pdev) == 0;
+		if (pci->msi)
+			nvkm_debug(&pci->subdev, "MSI enabled\n");
+	} else {
+		pci->msi = false;
+	}
+
 	return 0;
 }