Commit fe76fe49 authored by Ben Skeggs's avatar Ben Skeggs
Browse files

drm/nouveau/mc: implement intr handling on top of nvkm_intr



- new-style handlers can now be used here too
- decent clean-up

Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
Reviewed-by: default avatarLyude Paul <lyude@redhat.com>
parent e5f92c87
Loading
Loading
Loading
Loading
+2 −4
Original line number Diff line number Diff line
@@ -6,15 +6,14 @@
struct nvkm_mc {
	const struct nvkm_mc_func *func;
	struct nvkm_subdev subdev;

	struct nvkm_intr intr;
};

void nvkm_mc_enable(struct nvkm_device *, enum nvkm_subdev_type, int);
void nvkm_mc_disable(struct nvkm_device *, enum nvkm_subdev_type, int);
bool nvkm_mc_enabled(struct nvkm_device *, enum nvkm_subdev_type, int);
void nvkm_mc_reset(struct nvkm_device *, enum nvkm_subdev_type, int);
void nvkm_mc_intr(struct nvkm_device *, bool *handled);
void nvkm_mc_intr_unarm(struct nvkm_device *);
void nvkm_mc_intr_rearm(struct nvkm_device *);
void nvkm_mc_intr_mask(struct nvkm_device *, enum nvkm_subdev_type, int, bool enable);
void nvkm_mc_unk260(struct nvkm_device *, u32 data);

@@ -31,6 +30,5 @@ int gk104_mc_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct n
int gk20a_mc_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_mc **);
int gp100_mc_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_mc **);
int gp10b_mc_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_mc **);
int tu102_mc_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_mc **);
int ga100_mc_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_mc **);
#endif
+1 −9
Original line number Diff line number Diff line
@@ -25,8 +25,6 @@
#include <subdev/pci.h>
#include <subdev/top.h>

#include <subdev/mc.h>

static int
nvkm_intr_xlat(struct nvkm_subdev *subdev, struct nvkm_intr *intr,
	       enum nvkm_intr_type type, int *leaf, u32 *mask)
@@ -151,7 +149,6 @@ nvkm_intr_rearm_locked(struct nvkm_device *device)

	list_for_each_entry(intr, &device->intr.intr, head)
		intr->func->rearm(intr);
	nvkm_mc_intr_rearm(device);
}

static void
@@ -161,7 +158,6 @@ nvkm_intr_unarm_locked(struct nvkm_device *device)

	list_for_each_entry(intr, &device->intr.intr, head)
		intr->func->unarm(intr);
	nvkm_mc_intr_unarm(device);
}

static irqreturn_t
@@ -171,7 +167,7 @@ nvkm_intr(int irq, void *arg)
	struct nvkm_intr *intr;
	struct nvkm_inth *inth;
	irqreturn_t ret = IRQ_NONE;
	bool pending = false, handled;
	bool pending = false;
	int prio, leaf;

	/* Disable all top-level interrupt sources, and re-arm MSI interrupts. */
@@ -188,10 +184,6 @@ nvkm_intr(int irq, void *arg)
			pending = true;
	}

	nvkm_mc_intr(device, &handled);
	if (handled)
		ret = IRQ_HANDLED;

	if (!pending)
		goto done;

+5 −5
Original line number Diff line number Diff line
@@ -2412,7 +2412,7 @@ nv162_chipset = {
	.i2c      = { 0x00000001, gm200_i2c_new },
	.imem     = { 0x00000001, nv50_instmem_new },
	.ltc      = { 0x00000001, gp102_ltc_new },
	.mc       = { 0x00000001, tu102_mc_new },
	.mc       = { 0x00000001, gp100_mc_new },
	.mmu      = { 0x00000001, tu102_mmu_new },
	.pci      = { 0x00000001, gp100_pci_new },
	.pmu      = { 0x00000001, gp102_pmu_new },
@@ -2447,7 +2447,7 @@ nv164_chipset = {
	.i2c      = { 0x00000001, gm200_i2c_new },
	.imem     = { 0x00000001, nv50_instmem_new },
	.ltc      = { 0x00000001, gp102_ltc_new },
	.mc       = { 0x00000001, tu102_mc_new },
	.mc       = { 0x00000001, gp100_mc_new },
	.mmu      = { 0x00000001, tu102_mmu_new },
	.pci      = { 0x00000001, gp100_pci_new },
	.pmu      = { 0x00000001, gp102_pmu_new },
@@ -2482,7 +2482,7 @@ nv166_chipset = {
	.i2c      = { 0x00000001, gm200_i2c_new },
	.imem     = { 0x00000001, nv50_instmem_new },
	.ltc      = { 0x00000001, gp102_ltc_new },
	.mc       = { 0x00000001, tu102_mc_new },
	.mc       = { 0x00000001, gp100_mc_new },
	.mmu      = { 0x00000001, tu102_mmu_new },
	.pci      = { 0x00000001, gp100_pci_new },
	.pmu      = { 0x00000001, gp102_pmu_new },
@@ -2517,7 +2517,7 @@ nv167_chipset = {
	.i2c      = { 0x00000001, gm200_i2c_new },
	.imem     = { 0x00000001, nv50_instmem_new },
	.ltc      = { 0x00000001, gp102_ltc_new },
	.mc       = { 0x00000001, tu102_mc_new },
	.mc       = { 0x00000001, gp100_mc_new },
	.mmu      = { 0x00000001, tu102_mmu_new },
	.pci      = { 0x00000001, gp100_pci_new },
	.pmu      = { 0x00000001, gp102_pmu_new },
@@ -2552,7 +2552,7 @@ nv168_chipset = {
	.i2c      = { 0x00000001, gm200_i2c_new },
	.imem     = { 0x00000001, nv50_instmem_new },
	.ltc      = { 0x00000001, gp102_ltc_new },
	.mc       = { 0x00000001, tu102_mc_new },
	.mc       = { 0x00000001, gp100_mc_new },
	.mmu      = { 0x00000001, tu102_mmu_new },
	.pci      = { 0x00000001, gp100_pci_new },
	.pmu      = { 0x00000001, gp102_pmu_new },
+0 −1
Original line number Diff line number Diff line
@@ -13,5 +13,4 @@ nvkm-y += nvkm/subdev/mc/gk104.o
nvkm-y += nvkm/subdev/mc/gk20a.o
nvkm-y += nvkm/subdev/mc/gp100.o
nvkm-y += nvkm/subdev/mc/gp10b.o
nvkm-y += nvkm/subdev/mc/tu102.o
nvkm-y += nvkm/subdev/mc/ga100.o
+19 −94
Original line number Diff line number Diff line
@@ -37,86 +37,16 @@ nvkm_mc_unk260(struct nvkm_device *device, u32 data)
void
nvkm_mc_intr_mask(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, bool en)
{
	struct nvkm_mc *mc = device->mc;
	const struct nvkm_mc_map *map;
	if (likely(mc) && mc->func->intr_mask) {
		u32 mask = nvkm_top_intr_mask(device, type, inst);
		for (map = mc->func->intr; !mask && map->stat; map++) {
			if (map->type == type && map->inst == inst)
				mask = map->stat;
		}
		mc->func->intr_mask(mc, mask, en ? mask : 0);
	}
}

void
nvkm_mc_intr_unarm(struct nvkm_device *device)
{
	struct nvkm_mc *mc = device->mc;
	if (likely(mc))
		mc->func->intr_unarm(mc);
}

void
nvkm_mc_intr_rearm(struct nvkm_device *device)
{
	struct nvkm_mc *mc = device->mc;
	if (likely(mc))
		mc->func->intr_rearm(mc);
}

static u32
nvkm_mc_intr_stat(struct nvkm_mc *mc)
{
	u32 intr = mc->func->intr_stat(mc);
	if (WARN_ON_ONCE(intr == 0xffffffff))
		intr = 0; /* likely fallen off the bus */
	return intr;
}

void
nvkm_mc_intr(struct nvkm_device *device, bool *handled)
{
	struct nvkm_mc *mc = device->mc;
	struct nvkm_top *top = device->top;
	struct nvkm_top_device *tdev;
	struct nvkm_subdev *subdev;
	const struct nvkm_mc_map *map;
	u32 stat, intr;

	if (unlikely(!mc))
		return;

	stat = intr = nvkm_mc_intr_stat(mc);
	struct nvkm_subdev *subdev = nvkm_device_subdev(device, type, inst);

	if (top) {
		list_for_each_entry(tdev, &top->device, head) {
			if (tdev->intr >= 0 && (stat & BIT(tdev->intr))) {
				subdev = nvkm_device_subdev(device, tdev->type, tdev->inst);
	if (subdev) {
					nvkm_subdev_intr(subdev);
					stat &= ~BIT(tdev->intr);
					if (!stat)
						break;
				}
			}
		if (en)
			nvkm_intr_allow(subdev, NVKM_INTR_SUBDEV);
		else
			nvkm_intr_block(subdev, NVKM_INTR_SUBDEV);
	}
}

	for (map = mc->func->intr; map->stat; map++) {
		if (intr & map->stat) {
			subdev = nvkm_device_subdev(device, map->type, map->inst);
			if (subdev)
				nvkm_subdev_intr(subdev);
			stat &= ~map->stat;
		}
	}

	if (stat)
		nvkm_error(&mc->subdev, "intr %08x\n", stat);
	*handled = intr != 0;
}

static u32
nvkm_mc_reset_mask(struct nvkm_device *device, bool isauto, enum nvkm_subdev_type type, int inst)
{
@@ -177,20 +107,12 @@ nvkm_mc_enabled(struct nvkm_device *device, enum nvkm_subdev_type type, int inst
}


static int
nvkm_mc_fini(struct nvkm_subdev *subdev, bool suspend)
{
	nvkm_mc_intr_unarm(subdev->device);
	return 0;
}

static int
nvkm_mc_init(struct nvkm_subdev *subdev)
{
	struct nvkm_mc *mc = nvkm_mc(subdev);
	if (mc->func->init)
		mc->func->init(mc);
	nvkm_mc_intr_rearm(subdev->device);
	return 0;
}

@@ -204,24 +126,27 @@ static const struct nvkm_subdev_func
nvkm_mc = {
	.dtor = nvkm_mc_dtor,
	.init = nvkm_mc_init,
	.fini = nvkm_mc_fini,
};

void
nvkm_mc_ctor(const struct nvkm_mc_func *func, struct nvkm_device *device,
	     enum nvkm_subdev_type type, int inst, struct nvkm_mc *mc)
{
	nvkm_subdev_ctor(&nvkm_mc, device, type, inst, &mc->subdev);
	mc->func = func;
}

int
nvkm_mc_new_(const struct nvkm_mc_func *func, struct nvkm_device *device,
	     enum nvkm_subdev_type type, int inst, struct nvkm_mc **pmc)
{
	struct nvkm_mc *mc;
	int ret;

	if (!(mc = *pmc = kzalloc(sizeof(*mc), GFP_KERNEL)))
		return -ENOMEM;
	nvkm_mc_ctor(func, device, type, inst, *pmc);

	nvkm_subdev_ctor(&nvkm_mc, device, type, inst, &mc->subdev);
	mc->func = func;

	if (mc->func->intr) {
		ret = nvkm_intr_add(mc->func->intr, mc->func->intrs, &mc->subdev,
				    mc->func->intr_nonstall ? 2 : 1, &mc->intr);
		if (ret)
			return ret;
	}

	return 0;
}
Loading