diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau')
20 files changed, 102 insertions, 70 deletions
diff --git a/drivers/gpu/drm/nouveau/dispnv04/crtc.c b/drivers/gpu/drm/nouveau/dispnv04/crtc.c index a34924523133..a34917b048f9 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/crtc.c +++ b/drivers/gpu/drm/nouveau/dispnv04/crtc.c @@ -1122,18 +1122,11 @@ nv04_page_flip_emit(struct nouveau_channel *chan, PUSH_NVSQ(push, NV_SW, NV_SW_PAGE_FLIP, 0x00000000); PUSH_KICK(push); - ret = nouveau_fence_new(pfence); + ret = nouveau_fence_new(pfence, chan); if (ret) goto fail; - ret = nouveau_fence_emit(*pfence, chan); - if (ret) - goto fail_fence_unref; - return 0; - -fail_fence_unref: - nouveau_fence_unref(pfence); fail: spin_lock_irqsave(&dev->event_lock, flags); list_del(&s->head); diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index 9066a1263b73..a0ac8c258d9f 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -1888,6 +1888,8 @@ nv50_pior_destroy(struct drm_encoder *encoder) nvif_outp_dtor(&nv_encoder->outp); drm_encoder_cleanup(encoder); + + mutex_destroy(&nv_encoder->dp.hpd_irq_lock); kfree(encoder); } @@ -1928,6 +1930,8 @@ nv50_pior_create(struct nouveau_encoder *nv_encoder) nv_encoder->i2c = ddc; + mutex_init(&nv_encoder->dp.hpd_irq_lock); + encoder = to_drm_encoder(nv_encoder); drm_encoder_init(connector->dev, encoder, &nv50_pior_func, type, "pior-%04x-%04x", dcbe->hasht, dcbe->hashm); diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/i2c.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/i2c.h index 40a1065ae626..ef441dfdea09 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/i2c.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/i2c.h @@ -16,7 +16,7 @@ struct nvkm_i2c_bus { const struct nvkm_i2c_bus_func *func; struct nvkm_i2c_pad *pad; #define NVKM_I2C_BUS_CCB(n) /* 'n' is ccb index */ (n) -#define NVKM_I2C_BUS_EXT(n) /* 'n' is dcb external encoder type */ ((n) + 0x100) +#define NVKM_I2C_BUS_EXT(n) /* 'n' is dcb external encoder type */ ((n) + 0x10) #define NVKM_I2C_BUS_PRI /* ccb primary comm. port */ -1 #define NVKM_I2C_BUS_SEC /* ccb secondary comm. port */ -2 int id; @@ -38,7 +38,7 @@ struct nvkm_i2c_aux { const struct nvkm_i2c_aux_func *func; struct nvkm_i2c_pad *pad; #define NVKM_I2C_AUX_CCB(n) /* 'n' is ccb index */ (n) -#define NVKM_I2C_AUX_EXT(n) /* 'n' is dcb external encoder type */ ((n) + 0x100) +#define NVKM_I2C_AUX_EXT(n) /* 'n' is dcb external encoder type */ ((n) + 0x10) int id; struct mutex mutex; diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 19cab37ac69c..0f3bd187ede6 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -875,16 +875,10 @@ nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, if (ret) goto out_unlock; - ret = nouveau_fence_new(&fence); + ret = nouveau_fence_new(&fence, chan); if (ret) goto out_unlock; - ret = nouveau_fence_emit(fence, chan); - if (ret) { - nouveau_fence_unref(&fence); - goto out_unlock; - } - /* TODO: figure out a better solution here * * wait on the fence here explicitly as going through diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.c b/drivers/gpu/drm/nouveau/nouveau_chan.c index 1fd5ccf41128..bb3d6e5c122f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_chan.c +++ b/drivers/gpu/drm/nouveau/nouveau_chan.c @@ -70,11 +70,9 @@ nouveau_channel_idle(struct nouveau_channel *chan) struct nouveau_fence *fence = NULL; int ret; - ret = nouveau_fence_new(&fence); + ret = nouveau_fence_new(&fence, chan); if (!ret) { - ret = nouveau_fence_emit(fence, chan); - if (!ret) - ret = nouveau_fence_wait(fence, false, false); + ret = nouveau_fence_wait(fence, false, false); nouveau_fence_unref(&fence); } diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 94498c15b50e..856b3ef5edb8 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -988,7 +988,7 @@ nouveau_connector_get_modes(struct drm_connector *connector) /* Determine display colour depth for everything except LVDS now, * DP requires this before mode_valid() is called. */ - if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS && nv_connector->native_mode) + if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS) nouveau_connector_detect_depth(connector); /* Find the native mode if this is a digital panel, if we didn't @@ -1433,8 +1433,7 @@ nouveau_connector_create(struct drm_device *dev, int index) if (ret) { nvif_event_dtor(&nv_connector->hpd); nvif_conn_dtor(&nv_connector->conn); - kfree(nv_connector); - return ERR_PTR(ret); + goto drm_conn_err; } } } @@ -1482,4 +1481,9 @@ nouveau_connector_create(struct drm_device *dev, int index) drm_connector_register(connector); return connector; + +drm_conn_err: + drm_connector_cleanup(connector); + kfree(nv_connector); + return ERR_PTR(ret); } diff --git a/drivers/gpu/drm/nouveau/nouveau_dmem.c b/drivers/gpu/drm/nouveau/nouveau_dmem.c index 61e84562094a..12feecf71e75 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dmem.c +++ b/drivers/gpu/drm/nouveau/nouveau_dmem.c @@ -209,8 +209,7 @@ static vm_fault_t nouveau_dmem_migrate_to_ram(struct vm_fault *vmf) goto done; } - if (!nouveau_fence_new(&fence)) - nouveau_fence_emit(fence, dmem->migrate.chan); + nouveau_fence_new(&fence, dmem->migrate.chan); migrate_vma_pages(&args); nouveau_dmem_fence_done(&fence); dma_unmap_page(drm->dev->dev, dma_addr, PAGE_SIZE, DMA_BIDIRECTIONAL); @@ -403,8 +402,7 @@ nouveau_dmem_evict_chunk(struct nouveau_dmem_chunk *chunk) } } - if (!nouveau_fence_new(&fence)) - nouveau_fence_emit(fence, chunk->drm->dmem->migrate.chan); + nouveau_fence_new(&fence, chunk->drm->dmem->migrate.chan); migrate_device_pages(src_pfns, dst_pfns, npages); nouveau_dmem_fence_done(&fence); migrate_device_finalize(src_pfns, dst_pfns, npages); @@ -677,8 +675,7 @@ static void nouveau_dmem_migrate_chunk(struct nouveau_drm *drm, addr += PAGE_SIZE; } - if (!nouveau_fence_new(&fence)) - nouveau_fence_emit(fence, drm->dmem->migrate.chan); + nouveau_fence_new(&fence, drm->dmem->migrate.chan); migrate_vma_pages(args); nouveau_dmem_fence_done(&fence); nouveau_pfns_map(svmm, args->vma->vm_mm, args->start, pfns, i); diff --git a/drivers/gpu/drm/nouveau/nouveau_exec.c b/drivers/gpu/drm/nouveau/nouveau_exec.c index b4239af29e5a..bf6c12f4342a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_exec.c +++ b/drivers/gpu/drm/nouveau/nouveau_exec.c @@ -96,7 +96,8 @@ nouveau_exec_job_submit(struct nouveau_job *job) unsigned long index; int ret; - ret = nouveau_fence_new(&exec_job->fence); + /* Create a new fence, but do not emit yet. */ + ret = nouveau_fence_create(&exec_job->fence, exec_job->chan); if (ret) return ret; @@ -170,13 +171,17 @@ nouveau_exec_job_run(struct nouveau_job *job) nv50_dma_push(chan, p->va, p->va_len, no_prefetch); } - ret = nouveau_fence_emit(fence, chan); + ret = nouveau_fence_emit(fence); if (ret) { + nouveau_fence_unref(&exec_job->fence); NV_PRINTK(err, job->cli, "error fencing pushbuf: %d\n", ret); WIND_RING(chan); return ERR_PTR(ret); } + /* The fence was emitted successfully, set the job's fence pointer to + * NULL in order to avoid freeing it up when the job is cleaned up. + */ exec_job->fence = NULL; return &fence->base; @@ -189,7 +194,7 @@ nouveau_exec_job_free(struct nouveau_job *job) nouveau_job_free(job); - nouveau_fence_unref(&exec_job->fence); + kfree(exec_job->fence); kfree(exec_job->push.s); kfree(exec_job); } diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c index 77c739a55b19..61d9e70da9fd 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.c +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c @@ -205,16 +205,13 @@ nouveau_fence_context_new(struct nouveau_channel *chan, struct nouveau_fence_cha } int -nouveau_fence_emit(struct nouveau_fence *fence, struct nouveau_channel *chan) +nouveau_fence_emit(struct nouveau_fence *fence) { + struct nouveau_channel *chan = fence->channel; struct nouveau_fence_chan *fctx = chan->fence; struct nouveau_fence_priv *priv = (void*)chan->drm->fence; int ret; - if (unlikely(!chan->fence)) - return -ENODEV; - - fence->channel = chan; fence->timeout = jiffies + (15 * HZ); if (priv->uevent) @@ -406,18 +403,41 @@ nouveau_fence_unref(struct nouveau_fence **pfence) } int -nouveau_fence_new(struct nouveau_fence **pfence) +nouveau_fence_create(struct nouveau_fence **pfence, + struct nouveau_channel *chan) { struct nouveau_fence *fence; + if (unlikely(!chan->fence)) + return -ENODEV; + fence = kzalloc(sizeof(*fence), GFP_KERNEL); if (!fence) return -ENOMEM; + fence->channel = chan; + *pfence = fence; return 0; } +int +nouveau_fence_new(struct nouveau_fence **pfence, + struct nouveau_channel *chan) +{ + int ret = 0; + + ret = nouveau_fence_create(pfence, chan); + if (ret) + return ret; + + ret = nouveau_fence_emit(*pfence); + if (ret) + nouveau_fence_unref(pfence); + + return ret; +} + static const char *nouveau_fence_get_get_driver_name(struct dma_fence *fence) { return "nouveau"; diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.h b/drivers/gpu/drm/nouveau/nouveau_fence.h index 2c72d96ef17d..64d33ae7f356 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.h +++ b/drivers/gpu/drm/nouveau/nouveau_fence.h @@ -17,10 +17,11 @@ struct nouveau_fence { unsigned long timeout; }; -int nouveau_fence_new(struct nouveau_fence **); +int nouveau_fence_create(struct nouveau_fence **, struct nouveau_channel *); +int nouveau_fence_new(struct nouveau_fence **, struct nouveau_channel *); void nouveau_fence_unref(struct nouveau_fence **); -int nouveau_fence_emit(struct nouveau_fence *, struct nouveau_channel *); +int nouveau_fence_emit(struct nouveau_fence *); bool nouveau_fence_done(struct nouveau_fence *); int nouveau_fence_wait(struct nouveau_fence *, bool lazy, bool intr); int nouveau_fence_sync(struct nouveau_bo *, struct nouveau_channel *, bool exclusive, bool intr); diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index c0b10d8d3d03..a0d303e5ce3d 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -914,11 +914,8 @@ revalidate: } } - ret = nouveau_fence_new(&fence); - if (!ret) - ret = nouveau_fence_emit(fence, chan); + ret = nouveau_fence_new(&fence, chan); if (ret) { - nouveau_fence_unref(&fence); NV_PRINTK(err, cli, "error fencing pushbuf: %d\n", ret); WIND_RING(chan); goto out; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c index c6eeb8e44c15..ff82bb248492 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c @@ -81,20 +81,29 @@ nvkm_uconn_uevent(struct nvkm_object *object, void *argv, u32 argc, struct nvkm_ return -ENOSYS; list_for_each_entry(outp, &conn->disp->outps, head) { - if (outp->info.connector == conn->index && outp->dp.aux) { - if (args->v0.types & NVIF_CONN_EVENT_V0_PLUG ) bits |= NVKM_I2C_PLUG; - if (args->v0.types & NVIF_CONN_EVENT_V0_UNPLUG) bits |= NVKM_I2C_UNPLUG; - if (args->v0.types & NVIF_CONN_EVENT_V0_IRQ ) bits |= NVKM_I2C_IRQ; + if (outp->info.connector == conn->index) + break; + } - return nvkm_uevent_add(uevent, &device->i2c->event, outp->dp.aux->id, bits, - nvkm_uconn_uevent_aux); - } + if (&outp->head == &conn->disp->outps) + return -EINVAL; + + if (outp->dp.aux && !outp->info.location) { + if (args->v0.types & NVIF_CONN_EVENT_V0_PLUG ) bits |= NVKM_I2C_PLUG; + if (args->v0.types & NVIF_CONN_EVENT_V0_UNPLUG) bits |= NVKM_I2C_UNPLUG; + if (args->v0.types & NVIF_CONN_EVENT_V0_IRQ ) bits |= NVKM_I2C_IRQ; + + return nvkm_uevent_add(uevent, &device->i2c->event, outp->dp.aux->id, bits, + nvkm_uconn_uevent_aux); } if (args->v0.types & NVIF_CONN_EVENT_V0_PLUG ) bits |= NVKM_GPIO_HI; if (args->v0.types & NVIF_CONN_EVENT_V0_UNPLUG) bits |= NVKM_GPIO_LO; - if (args->v0.types & NVIF_CONN_EVENT_V0_IRQ) - return -EINVAL; + if (args->v0.types & NVIF_CONN_EVENT_V0_IRQ) { + /* TODO: support DP IRQ on ANX9805 and remove this hack. */ + if (!outp->info.location) + return -EINVAL; + } return nvkm_uevent_add(uevent, &device->gpio->event, conn->info.hpd, bits, nvkm_uconn_uevent_gpio); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h index 00dbeda7e346..de161e7a04aa 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h @@ -117,6 +117,7 @@ void gk104_grctx_generate_r418800(struct gf100_gr *); extern const struct gf100_grctx_func gk110_grctx; void gk110_grctx_generate_r419eb0(struct gf100_gr *); +void gk110_grctx_generate_r419f78(struct gf100_gr *); extern const struct gf100_grctx_func gk110b_grctx; extern const struct gf100_grctx_func gk208_grctx; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c index 94233d0119df..52a234b1ef01 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c @@ -906,7 +906,9 @@ static void gk104_grctx_generate_r419f78(struct gf100_gr *gr) { struct nvkm_device *device = gr->base.engine.subdev.device; - nvkm_mask(device, 0x419f78, 0x00000001, 0x00000000); + + /* bit 3 set disables loads in fp helper invocations, we need it enabled */ + nvkm_mask(device, 0x419f78, 0x00000009, 0x00000000); } void diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110.c index 4391458e1fb2..3acdd9eeb74a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110.c @@ -820,6 +820,15 @@ gk110_grctx_generate_r419eb0(struct gf100_gr *gr) nvkm_mask(device, 0x419eb0, 0x00001000, 0x00001000); } +void +gk110_grctx_generate_r419f78(struct gf100_gr *gr) +{ + struct nvkm_device *device = gr->base.engine.subdev.device; + + /* bit 3 set disables loads in fp helper invocations, we need it enabled */ + nvkm_mask(device, 0x419f78, 0x00000008, 0x00000000); +} + const struct gf100_grctx_func gk110_grctx = { .main = gf100_grctx_generate_main, @@ -854,4 +863,5 @@ gk110_grctx = { .gpc_tpc_nr = gk104_grctx_generate_gpc_tpc_nr, .r418800 = gk104_grctx_generate_r418800, .r419eb0 = gk110_grctx_generate_r419eb0, + .r419f78 = gk110_grctx_generate_r419f78, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110b.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110b.c index 7b9a34f9ec3c..5597e87624ac 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110b.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110b.c @@ -103,4 +103,5 @@ gk110b_grctx = { .gpc_tpc_nr = gk104_grctx_generate_gpc_tpc_nr, .r418800 = gk104_grctx_generate_r418800, .r419eb0 = gk110_grctx_generate_r419eb0, + .r419f78 = gk110_grctx_generate_r419f78, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk208.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk208.c index c78d07a8bb7d..612656496541 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk208.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk208.c @@ -568,4 +568,5 @@ gk208_grctx = { .dist_skip_table = gf117_grctx_generate_dist_skip_table, .gpc_tpc_nr = gk104_grctx_generate_gpc_tpc_nr, .r418800 = gk104_grctx_generate_r418800, + .r419f78 = gk110_grctx_generate_r419f78, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c index beac66eb2a80..9906974ac3f0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c @@ -988,4 +988,5 @@ gm107_grctx = { .r406500 = gm107_grctx_generate_r406500, .gpc_tpc_nr = gk104_grctx_generate_gpc_tpc_nr, .r419e00 = gm107_grctx_generate_r419e00, + .r419f78 = gk110_grctx_generate_r419f78, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c index 3b6c8100a242..a7775aa18541 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c @@ -206,19 +206,6 @@ tu102_gr_av_to_init_veid(struct nvkm_blob *blob, struct gf100_gr_pack **ppack) return gk20a_gr_av_to_init_(blob, 64, 0x00100000, ppack); } -int -tu102_gr_load(struct gf100_gr *gr, int ver, const struct gf100_gr_fwif *fwif) -{ - int ret; - - ret = gm200_gr_load(gr, ver, fwif); - if (ret) - return ret; - - return gk20a_gr_load_net(gr, "gr/", "sw_veid_bundle_init", ver, tu102_gr_av_to_init_veid, - &gr->bundle_veid); -} - static const struct gf100_gr_fwif tu102_gr_fwif[] = { { 0, gm200_gr_load, &tu102_gr, &gp108_gr_fecs_acr, &gp108_gr_gpccs_acr }, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c index 976539de4220..731b2f68d3db 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c @@ -260,10 +260,11 @@ nvkm_i2c_new_(const struct nvkm_i2c_func *func, struct nvkm_device *device, { struct nvkm_bios *bios = device->bios; struct nvkm_i2c *i2c; + struct nvkm_i2c_aux *aux; struct dcb_i2c_entry ccbE; struct dcb_output dcbE; u8 ver, hdr; - int ret, i; + int ret, i, ids; if (!(i2c = *pi2c = kzalloc(sizeof(*i2c), GFP_KERNEL))) return -ENOMEM; @@ -406,5 +407,11 @@ nvkm_i2c_new_(const struct nvkm_i2c_func *func, struct nvkm_device *device, } } - return nvkm_event_init(&nvkm_i2c_intr_func, &i2c->subdev, 4, i, &i2c->event); + ids = 0; + list_for_each_entry(aux, &i2c->aux, head) + ids = max(ids, aux->id + 1); + if (!ids) + return 0; + + return nvkm_event_init(&nvkm_i2c_intr_func, &i2c->subdev, 4, ids, &i2c->event); } |