These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / gpu / drm / nouveau / nvkm / subdev / mc / base.c
index 5b051a2..954fbbe 100644 (file)
  */
 #include "priv.h"
 
-#include <core/device.h>
 #include <core/option.h>
 
-static inline void
-nvkm_mc_unk260(struct nvkm_mc *pmc, u32 data)
+void
+nvkm_mc_unk260(struct nvkm_mc *mc, u32 data)
 {
-       const struct nvkm_mc_oclass *impl = (void *)nv_oclass(pmc);
-       if (impl->unk260)
-               impl->unk260(pmc, data);
+       if (mc->func->unk260)
+               mc->func->unk260(mc, data);
 }
 
-static inline u32
-nvkm_mc_intr_mask(struct nvkm_mc *pmc)
+void
+nvkm_mc_intr_unarm(struct nvkm_mc *mc)
 {
-       u32 intr = nv_rd32(pmc, 0x000100);
-       if (intr == 0xffffffff) /* likely fallen off the bus */
-               intr = 0x00000000;
-       return intr;
+       return mc->func->intr_unarm(mc);
 }
 
-static irqreturn_t
-nvkm_mc_intr(int irq, void *arg)
+void
+nvkm_mc_intr_rearm(struct nvkm_mc *mc)
 {
-       struct nvkm_mc *pmc = arg;
-       const struct nvkm_mc_oclass *oclass = (void *)nv_object(pmc)->oclass;
-       const struct nvkm_mc_intr *map = oclass->intr;
-       struct nvkm_subdev *unit;
-       u32 intr;
+       return mc->func->intr_rearm(mc);
+}
 
-       nv_wr32(pmc, 0x000140, 0x00000000);
-       nv_rd32(pmc, 0x000140);
-       intr = nvkm_mc_intr_mask(pmc);
-       if (pmc->use_msi)
-               oclass->msi_rearm(pmc);
+static u32
+nvkm_mc_intr_mask(struct nvkm_mc *mc)
+{
+       u32 intr = mc->func->intr_mask(mc);
+       if (WARN_ON_ONCE(intr == 0xffffffff))
+               intr = 0; /* likely fallen off the bus */
+       return intr;
+}
 
-       if (intr) {
-               u32 stat = intr = nvkm_mc_intr_mask(pmc);
-               while (map->stat) {
-                       if (intr & map->stat) {
-                               unit = nvkm_subdev(pmc, map->unit);
-                               if (unit && unit->intr)
-                                       unit->intr(unit);
-                               stat &= ~map->stat;
-                       }
-                       map++;
+void
+nvkm_mc_intr(struct nvkm_mc *mc, bool *handled)
+{
+       struct nvkm_device *device = mc->subdev.device;
+       struct nvkm_subdev *subdev;
+       const struct nvkm_mc_intr *map = mc->func->intr;
+       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)
-                       nv_error(pmc, "unknown intr 0x%08x\n", stat);
+               map++;
        }
 
-       nv_wr32(pmc, 0x000140, 0x00000001);
-       return intr ? IRQ_HANDLED : IRQ_NONE;
+       if (stat)
+               nvkm_error(&mc->subdev, "intr %08x\n", stat);
+       *handled = intr != 0;
 }
 
-int
-_nvkm_mc_fini(struct nvkm_object *object, bool suspend)
+static int
+nvkm_mc_fini(struct nvkm_subdev *subdev, bool suspend)
 {
-       struct nvkm_mc *pmc = (void *)object;
-       nv_wr32(pmc, 0x000140, 0x00000000);
-       return nvkm_subdev_fini(&pmc->base, suspend);
+       struct nvkm_mc *mc = nvkm_mc(subdev);
+       nvkm_mc_intr_unarm(mc);
+       return 0;
 }
 
-int
-_nvkm_mc_init(struct nvkm_object *object)
+static int
+nvkm_mc_init(struct nvkm_subdev *subdev)
 {
-       struct nvkm_mc *pmc = (void *)object;
-       int ret = nvkm_subdev_init(&pmc->base);
-       if (ret)
-               return ret;
-       nv_wr32(pmc, 0x000140, 0x00000001);
+       struct nvkm_mc *mc = nvkm_mc(subdev);
+       if (mc->func->init)
+               mc->func->init(mc);
+       nvkm_mc_intr_rearm(mc);
        return 0;
 }
 
-void
-_nvkm_mc_dtor(struct nvkm_object *object)
+static void *
+nvkm_mc_dtor(struct nvkm_subdev *subdev)
 {
-       struct nvkm_device *device = nv_device(object);
-       struct nvkm_mc *pmc = (void *)object;
-       free_irq(pmc->irq, pmc);
-       if (pmc->use_msi)
-               pci_disable_msi(device->pdev);
-       nvkm_subdev_destroy(&pmc->base);
+       return nvkm_mc(subdev);
 }
 
+static const struct nvkm_subdev_func
+nvkm_mc = {
+       .dtor = nvkm_mc_dtor,
+       .init = nvkm_mc_init,
+       .fini = nvkm_mc_fini,
+};
+
 int
-nvkm_mc_create_(struct nvkm_object *parent, struct nvkm_object *engine,
-               struct nvkm_oclass *bclass, int length, void **pobject)
+nvkm_mc_new_(const struct nvkm_mc_func *func, struct nvkm_device *device,
+            int index, struct nvkm_mc **pmc)
 {
-       const struct nvkm_mc_oclass *oclass = (void *)bclass;
-       struct nvkm_device *device = nv_device(parent);
-       struct nvkm_mc *pmc;
-       int ret;
-
-       ret = nvkm_subdev_create_(parent, engine, bclass, 0, "PMC",
-                                 "master", length, pobject);
-       pmc = *pobject;
-       if (ret)
-               return ret;
-
-       pmc->unk260 = nvkm_mc_unk260;
-
-       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:
-                               pmc->use_msi = true;
-                               break;
-                       }
-               }
-
-               pmc->use_msi = nvkm_boolopt(device->cfgopt, "NvMSI",
-                                           pmc->use_msi);
-
-               if (pmc->use_msi && oclass->msi_rearm) {
-                       pmc->use_msi = pci_enable_msi(device->pdev) == 0;
-                       if (pmc->use_msi) {
-                               nv_info(pmc, "MSI interrupts enabled\n");
-                               oclass->msi_rearm(pmc);
-                       }
-               } else {
-                       pmc->use_msi = false;
-               }
-       }
-
-       ret = nv_device_get_irq(device, true);
-       if (ret < 0)
-               return ret;
-       pmc->irq = ret;
+       struct nvkm_mc *mc;
 
-       ret = request_irq(pmc->irq, nvkm_mc_intr, IRQF_SHARED, "nvkm", pmc);
-       if (ret < 0)
-               return ret;
+       if (!(mc = *pmc = kzalloc(sizeof(*mc), GFP_KERNEL)))
+               return -ENOMEM;
 
+       nvkm_subdev_ctor(&nvkm_mc, device, index, 0, &mc->subdev);
+       mc->func = func;
        return 0;
 }