bool use_msi;
 };
 
+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 **);
 
                mc->func->unk260(mc, data);
 }
 
-static inline u32
+void
+nvkm_mc_intr_unarm(struct nvkm_mc *mc)
+{
+       return mc->func->intr_unarm(mc);
+}
+
+void
+nvkm_mc_intr_rearm(struct nvkm_mc *mc)
+{
+       return mc->func->intr_rearm(mc);
+}
+
+u32
 nvkm_mc_intr_mask(struct nvkm_mc *mc)
 {
-       struct nvkm_device *device = mc->subdev.device;
-       u32 intr = nvkm_rd32(device, 0x000100);
-       if (intr == 0xffffffff) /* likely fallen off the bus */
-               intr = 0x00000000;
+       u32 intr = mc->func->intr_mask(mc);
+       if (WARN_ON_ONCE(intr == 0xffffffff))
+               intr = 0; /* likely fallen off the bus */
        return intr;
 }
 
        struct nvkm_subdev *unit;
        u32 intr;
 
-       nvkm_wr32(device, 0x000140, 0x00000000);
-       nvkm_rd32(device, 0x000140);
+       nvkm_mc_intr_unarm(mc);
        intr = nvkm_mc_intr_mask(mc);
        if (mc->use_msi)
                mc->func->msi_rearm(mc);
                        nvkm_error(subdev, "unknown intr %08x\n", stat);
        }
 
-       nvkm_wr32(device, 0x000140, 0x00000001);
+       nvkm_mc_intr_rearm(mc);
        return intr ? IRQ_HANDLED : IRQ_NONE;
 }
 
 static int
 nvkm_mc_fini(struct nvkm_subdev *subdev, bool suspend)
 {
-       nvkm_wr32(subdev->device, 0x000140, 0x00000000);
+       struct nvkm_mc *mc = nvkm_mc(subdev);
+       nvkm_mc_intr_unarm(mc);
        return 0;
 }
 
 nvkm_mc_init(struct nvkm_subdev *subdev)
 {
        struct nvkm_mc *mc = nvkm_mc(subdev);
-       struct nvkm_device *device = mc->subdev.device;
        if (mc->func->init)
                mc->func->init(mc);
-       nvkm_wr32(device, 0x000140, 0x00000001);
+       nvkm_mc_intr_rearm(mc);
        return 0;
 }
 
 
 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,
 };
 
 
 g98_mc = {
        .init = nv50_mc_init,
        .intr = g98_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,
 };
 
 
 gf100_mc = {
        .init = nv50_mc_init,
        .intr = gf100_mc_intr,
+       .intr_unarm = nv04_mc_intr_unarm,
+       .intr_rearm = nv04_mc_intr_rearm,
+       .intr_mask = nv04_mc_intr_mask,
        .msi_rearm = gf100_mc_msi_rearm,
        .unk260 = gf100_mc_unk260,
 };
 
 gf106_mc = {
        .init = nv50_mc_init,
        .intr = gf100_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,
        .unk260 = gf100_mc_unk260,
 };
 
 gk20a_mc = {
        .init = nv50_mc_init,
        .intr = gf100_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,
 };
 
 
        {}
 };
 
+void
+nv04_mc_intr_unarm(struct nvkm_mc *mc)
+{
+       struct nvkm_device *device = mc->subdev.device;
+       nvkm_wr32(device, 0x000140, 0x00000000);
+       nvkm_rd32(device, 0x000140);
+}
+
+void
+nv04_mc_intr_rearm(struct nvkm_mc *mc)
+{
+       struct nvkm_device *device = mc->subdev.device;
+       nvkm_wr32(device, 0x000140, 0x00000001);
+}
+
+u32
+nv04_mc_intr_mask(struct nvkm_mc *mc)
+{
+       return nvkm_rd32(mc->subdev.device, 0x000100);
+}
+
 void
 nv04_mc_init(struct nvkm_mc *mc)
 {
 nv04_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,
 };
 
 int
 
 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,
 };
 
 
 nv44_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,
        .msi_rearm = nv40_mc_msi_rearm,
 };
 
 
 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
 
 nv50_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 = nv50_mc_msi_rearm,
 };
 
 
 struct nvkm_mc_func {
        void (*init)(struct nvkm_mc *);
        const struct nvkm_mc_intr *intr;
+       /* disable reporting of interrupts to host */
+       void (*intr_unarm)(struct nvkm_mc *);
+       /* enable reporting of interrupts to host */
+       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);
 };
 
 void nv04_mc_init(struct nvkm_mc *);
 extern const struct nvkm_mc_intr nv04_mc_intr[];
+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 *);