Skip to content

Commit

Permalink
drm/nouveau/mc: implement intr handling on top of nvkm_intr
Browse files Browse the repository at this point in the history
- new-style handlers can now be used here too
- decent clean-up

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Reviewed-by: Lyude Paul <lyude@redhat.com>
  • Loading branch information
Ben Skeggs committed Nov 9, 2022
1 parent e5f92c8 commit fe76fe4
Show file tree
Hide file tree
Showing 21 changed files with 285 additions and 577 deletions.
6 changes: 2 additions & 4 deletions drivers/gpu/drm/nouveau/include/nvkm/subdev/mc.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -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
10 changes: 1 addition & 9 deletions drivers/gpu/drm/nouveau/nvkm/core/intr.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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. */
Expand All @@ -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;

Expand Down
10 changes: 5 additions & 5 deletions drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 },
Expand Down Expand Up @@ -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 },
Expand Down Expand Up @@ -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 },
Expand Down Expand Up @@ -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 },
Expand Down Expand Up @@ -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 },
Expand Down
1 change: 0 additions & 1 deletion drivers/gpu/drm/nouveau/nvkm/subdev/mc/Kbuild
Original file line number Diff line number Diff line change
Expand Up @@ -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
113 changes: 19 additions & 94 deletions drivers/gpu/drm/nouveau/nvkm/subdev/mc/base.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,84 +37,14 @@ 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;
}
}
}
}

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 (subdev) {
if (en)
nvkm_intr_allow(subdev, NVKM_INTR_SUBDEV);
else
nvkm_intr_block(subdev, NVKM_INTR_SUBDEV);
}

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

static u32
Expand Down Expand Up @@ -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;
}

Expand All @@ -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;
}
34 changes: 16 additions & 18 deletions drivers/gpu/drm/nouveau/nvkm/subdev/mc/g84.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,30 +34,28 @@ g84_mc_reset[] = {
{}
};

static const struct nvkm_mc_map
g84_mc_intr[] = {
{ 0x04000000, NVKM_ENGINE_DISP },
{ 0x00020000, NVKM_ENGINE_VP },
{ 0x00008000, NVKM_ENGINE_BSP },
{ 0x00004000, NVKM_ENGINE_CIPHER },
{ 0x00001000, NVKM_ENGINE_GR },
{ 0x00000100, NVKM_ENGINE_FIFO },
{ 0x00000001, NVKM_ENGINE_MPEG },
{ 0x0002d101, NVKM_SUBDEV_FB },
{ 0x10000000, NVKM_SUBDEV_BUS },
{ 0x00200000, NVKM_SUBDEV_GPIO },
{ 0x00200000, NVKM_SUBDEV_I2C },
{ 0x00100000, NVKM_SUBDEV_TIMER },
static const struct nvkm_intr_data
g84_mc_intrs[] = {
{ NVKM_ENGINE_DISP , 0, 0, 0x04000000, true },
{ NVKM_ENGINE_VP , 0, 0, 0x00020000, true },
{ NVKM_ENGINE_BSP , 0, 0, 0x00008000, true },
{ NVKM_ENGINE_CIPHER, 0, 0, 0x00004000, true },
{ NVKM_ENGINE_GR , 0, 0, 0x00001000, true },
{ NVKM_ENGINE_FIFO , 0, 0, 0x00000100, true },
{ NVKM_ENGINE_MPEG , 0, 0, 0x00000001, true },
{ NVKM_SUBDEV_FB , 0, 0, 0x0002d101, true },
{ NVKM_SUBDEV_BUS , 0, 0, 0x10000000, true },
{ NVKM_SUBDEV_GPIO , 0, 0, 0x00200000, true },
{ NVKM_SUBDEV_I2C , 0, 0, 0x00200000, true },
{ NVKM_SUBDEV_TIMER , 0, 0, 0x00100000, true },
{},
};

static const struct nvkm_mc_func
g84_mc = {
.init = nv50_mc_init,
.intr = g84_mc_intr,
.intr_unarm = nv04_mc_intr_unarm,
.intr_rearm = nv04_mc_intr_rearm,
.intr_stat = nv04_mc_intr_stat,
.intr = &nv04_mc_intr,
.intrs = g84_mc_intrs,
.reset = g84_mc_reset,
};

Expand Down
34 changes: 16 additions & 18 deletions drivers/gpu/drm/nouveau/nvkm/subdev/mc/g98.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,30 +34,28 @@ g98_mc_reset[] = {
{}
};

static const struct nvkm_mc_map
g98_mc_intr[] = {
{ 0x04000000, NVKM_ENGINE_DISP },
{ 0x00020000, NVKM_ENGINE_MSPDEC },
{ 0x00008000, NVKM_ENGINE_MSVLD },
{ 0x00004000, NVKM_ENGINE_SEC },
{ 0x00001000, NVKM_ENGINE_GR },
{ 0x00000100, NVKM_ENGINE_FIFO },
{ 0x00000001, NVKM_ENGINE_MSPPP },
{ 0x0002d101, NVKM_SUBDEV_FB },
{ 0x10000000, NVKM_SUBDEV_BUS },
{ 0x00200000, NVKM_SUBDEV_GPIO },
{ 0x00200000, NVKM_SUBDEV_I2C },
{ 0x00100000, NVKM_SUBDEV_TIMER },
static const struct nvkm_intr_data
g98_mc_intrs[] = {
{ NVKM_ENGINE_DISP , 0, 0, 0x04000000, true },
{ NVKM_ENGINE_MSPDEC, 0, 0, 0x00020000, true },
{ NVKM_ENGINE_MSVLD , 0, 0, 0x00008000, true },
{ NVKM_ENGINE_SEC , 0, 0, 0x00004000, true },
{ NVKM_ENGINE_GR , 0, 0, 0x00001000, true },
{ NVKM_ENGINE_FIFO , 0, 0, 0x00000100, true },
{ NVKM_ENGINE_MSPPP , 0, 0, 0x00000001, true },
{ NVKM_SUBDEV_FB , 0, 0, 0x0002d101, true },
{ NVKM_SUBDEV_BUS , 0, 0, 0x10000000, true },
{ NVKM_SUBDEV_GPIO , 0, 0, 0x00200000, true },
{ NVKM_SUBDEV_I2C , 0, 0, 0x00200000, true },
{ NVKM_SUBDEV_TIMER , 0, 0, 0x00100000, true },
{},
};

static const struct nvkm_mc_func
g98_mc = {
.init = nv50_mc_init,
.intr = g98_mc_intr,
.intr_unarm = nv04_mc_intr_unarm,
.intr_rearm = nv04_mc_intr_rearm,
.intr_stat = nv04_mc_intr_stat,
.intr = &nv04_mc_intr,
.intrs = g98_mc_intrs,
.reset = g98_mc_reset,
};

Expand Down
Loading

0 comments on commit fe76fe4

Please sign in to comment.