static void nv84_crypt_intr(struct nouveau_subdev *subdev) { struct nouveau_fifo *pfifo = nouveau_fifo(subdev); struct nouveau_engine *engine = nv_engine(subdev); struct nouveau_object *engctx; struct nv84_crypt_priv *priv = (void *)subdev; u32 stat = nv_rd32(priv, 0x102130); u32 mthd = nv_rd32(priv, 0x102190); u32 data = nv_rd32(priv, 0x102194); u32 inst = nv_rd32(priv, 0x102188) & 0x7fffffff; int chid; engctx = nouveau_engctx_get(engine, inst); chid = pfifo->chid(pfifo, engctx); if (stat) { nv_error(priv, "%s", ""); nouveau_bitfield_print(nv84_crypt_intr_mask, stat); pr_cont(" ch %d [0x%010llx %s] mthd 0x%04x data 0x%08x\n", chid, (u64)inst << 12, nouveau_client_name(engctx), mthd, data); } nv_wr32(priv, 0x102130, stat); nv_wr32(priv, 0x10200c, 0x10); nouveau_engctx_put(engctx); }
int nv84_fence_create(struct nouveau_drm *drm) { struct nouveau_fifo *pfifo = nouveau_fifo(drm->device); struct nv84_fence_priv *priv; int ret; priv = drm->fence = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; priv->base.dtor = nv84_fence_destroy; priv->base.suspend = nv84_fence_suspend; priv->base.resume = nv84_fence_resume; priv->base.context_new = nv84_fence_context_new; priv->base.context_del = nv84_fence_context_del; #ifdef __NetBSD__ spin_lock_init(&priv->base.waitlock); DRM_INIT_WAITQUEUE(&priv->base.waitqueue, "nvfenceq"); #else init_waitqueue_head(&priv->base.waiting); #endif priv->base.uevent = true; ret = nouveau_bo_new(drm->dev, 16 * (pfifo->max + 1), 0, TTM_PL_FLAG_VRAM, 0, 0, NULL, &priv->bo); if (ret == 0) { ret = nouveau_bo_pin(priv->bo, TTM_PL_FLAG_VRAM); if (ret == 0) { ret = nouveau_bo_map(priv->bo); if (ret) nouveau_bo_unpin(priv->bo); } if (ret) nouveau_bo_ref(NULL, &priv->bo); } if (ret == 0) ret = nouveau_bo_new(drm->dev, 16 * (pfifo->max + 1), 0, TTM_PL_FLAG_TT, 0, 0, NULL, &priv->bo_gart); if (ret == 0) { ret = nouveau_bo_pin(priv->bo_gart, TTM_PL_FLAG_TT); if (ret == 0) { ret = nouveau_bo_map(priv->bo_gart); if (ret) nouveau_bo_unpin(priv->bo_gart); } if (ret) nouveau_bo_ref(NULL, &priv->bo_gart); } if (ret) nv84_fence_destroy(drm); return ret; }
static void nv84_fence_resume(struct nouveau_drm *drm) { struct nouveau_fifo *pfifo = nouveau_fifo(drm->device); struct nv84_fence_priv *priv = drm->fence; int i; if (priv->suspend) { for (i = 0; i <= pfifo->max; i++) nouveau_bo_wr32(priv->bo, i*4, priv->suspend[i]); vfree(priv->suspend); priv->suspend = NULL; } }
static bool nv84_fence_suspend(struct nouveau_drm *drm) { struct nouveau_fifo *pfifo = nouveau_fifo(drm->device); struct nv84_fence_priv *priv = drm->fence; int i; priv->suspend = vmalloc((pfifo->max + 1) * sizeof(u32)); if (priv->suspend) { for (i = 0; i <= pfifo->max; i++) priv->suspend[i] = nouveau_bo_rd32(priv->bo, i*4); } return priv->suspend != NULL; }
static void nouveau_accel_init(struct nouveau_drm *drm) { struct nouveau_device *device = nv_device(drm->device); struct nouveau_object *object; u32 arg0, arg1; int ret; if (nouveau_noaccel || !nouveau_fifo(device) /*XXX*/) return; /* initialise synchronisation routines */ if (device->card_type < NV_10) ret = nv04_fence_create(drm); else if (device->chipset < 0x17) ret = nv10_fence_create(drm); else if (device->card_type < NV_50) ret = nv17_fence_create(drm); else if (device->chipset < 0x84) ret = nv50_fence_create(drm); else if (device->card_type < NV_C0) ret = nv84_fence_create(drm); else ret = nvc0_fence_create(drm); if (ret) { NV_ERROR(drm, "failed to initialise sync subsystem, %d\n", ret); nouveau_accel_fini(drm); return; } if (device->card_type >= NV_E0) { ret = nouveau_channel_new(drm, &drm->client, NVDRM_DEVICE, NVDRM_CHAN + 1, NVE0_CHANNEL_IND_ENGINE_CE0 | NVE0_CHANNEL_IND_ENGINE_CE1, 0, &drm->cechan); if (ret) NV_ERROR(drm, "failed to create ce channel, %d\n", ret); arg0 = NVE0_CHANNEL_IND_ENGINE_GR; arg1 = 1; } else { arg0 = NvDmaFB; arg1 = NvDmaTT; } ret = nouveau_channel_new(drm, &drm->client, NVDRM_DEVICE, NVDRM_CHAN, arg0, arg1, &drm->channel); if (ret) { NV_ERROR(drm, "failed to create kernel channel, %d\n", ret); nouveau_accel_fini(drm); return; } if (device->card_type < NV_C0) { ret = nouveau_gpuobj_new(drm->device, NULL, 32, 0, 0, &drm->notify); if (ret) { NV_ERROR(drm, "failed to allocate notifier, %d\n", ret); nouveau_accel_fini(drm); return; } ret = nouveau_object_new(nv_object(drm), drm->channel->handle, NvNotify0, 0x003d, &(struct nv_dma_class) { .flags = NV_DMA_TARGET_VRAM | NV_DMA_ACCESS_RDWR, .start = drm->notify->addr, .limit = drm->notify->addr + 31 }, sizeof(struct nv_dma_class),
static void nouveau_accel_init(struct nouveau_drm *drm) { struct nouveau_device *device = nv_device(drm->device); struct nouveau_object *object; u32 arg0, arg1; int ret; if (nouveau_noaccel || !nouveau_fifo(device) /*XXX*/) return; /* initialise synchronisation routines */ if (device->card_type < NV_10) ret = nv04_fence_create(drm); else if (device->card_type < NV_11 || device->chipset < 0x17) ret = nv10_fence_create(drm); else if (device->card_type < NV_50) ret = nv17_fence_create(drm); else if (device->chipset < 0x84) ret = nv50_fence_create(drm); else if (device->card_type < NV_C0) ret = nv84_fence_create(drm); else ret = nvc0_fence_create(drm); if (ret) { NV_ERROR(drm, "failed to initialise sync subsystem, %d\n", ret); nouveau_accel_fini(drm); return; } if (device->card_type >= NV_E0) { ret = nouveau_channel_new(drm, &drm->client, NVDRM_DEVICE, NVDRM_CHAN + 1, NVE0_CHANNEL_IND_ENGINE_CE0 | NVE0_CHANNEL_IND_ENGINE_CE1, 0, &drm->cechan); if (ret) NV_ERROR(drm, "failed to create ce channel, %d\n", ret); arg0 = NVE0_CHANNEL_IND_ENGINE_GR; arg1 = 1; } else if (device->chipset >= 0xa3 && device->chipset != 0xaa && device->chipset != 0xac) { ret = nouveau_channel_new(drm, &drm->client, NVDRM_DEVICE, NVDRM_CHAN + 1, NvDmaFB, NvDmaTT, &drm->cechan); if (ret) NV_ERROR(drm, "failed to create ce channel, %d\n", ret); arg0 = NvDmaFB; arg1 = NvDmaTT; } else { arg0 = NvDmaFB; arg1 = NvDmaTT; } ret = nouveau_channel_new(drm, &drm->client, NVDRM_DEVICE, NVDRM_CHAN, arg0, arg1, &drm->channel); if (ret) { NV_ERROR(drm, "failed to create kernel channel, %d\n", ret); nouveau_accel_fini(drm); return; } ret = nouveau_object_new(nv_object(drm), NVDRM_CHAN, NVDRM_NVSW, nouveau_abi16_swclass(drm), NULL, 0, &object); if (ret == 0) { struct nouveau_software_chan *swch = (void *)object->parent; ret = RING_SPACE(drm->channel, 2); if (ret == 0) { if (device->card_type < NV_C0) { BEGIN_NV04(drm->channel, NvSubSw, 0, 1); OUT_RING (drm->channel, NVDRM_NVSW); } else if (device->card_type < NV_E0) { BEGIN_NVC0(drm->channel, FermiSw, 0, 1); OUT_RING (drm->channel, 0x001f0000); } } swch = (void *)object->parent; swch->flip = nouveau_flip_complete; swch->flip_data = drm->channel; } if (ret) { NV_ERROR(drm, "failed to allocate software object, %d\n", ret); nouveau_accel_fini(drm); return; } if (device->card_type < NV_C0) { ret = nouveau_gpuobj_new(drm->device, NULL, 32, 0, 0, &drm->notify); if (ret) { NV_ERROR(drm, "failed to allocate notifier, %d\n", ret); nouveau_accel_fini(drm); return; } ret = nouveau_object_new(nv_object(drm), drm->channel->handle, NvNotify0, 0x003d, &(struct nv_dma_class) { .flags = NV_DMA_TARGET_VRAM | NV_DMA_ACCESS_RDWR, .start = drm->notify->addr, .limit = drm->notify->addr + 31 }, sizeof(struct nv_dma_class),