diff options
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/cde_gk20a.c | 69 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/cde_gk20a.h | 1 |
2 files changed, 56 insertions, 14 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/cde_gk20a.c b/drivers/gpu/nvgpu/gk20a/cde_gk20a.c index 1c230be6..7931b83f 100644 --- a/drivers/gpu/nvgpu/gk20a/cde_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/cde_gk20a.c | |||
@@ -34,6 +34,8 @@ | |||
34 | #include "hw_ccsr_gk20a.h" | 34 | #include "hw_ccsr_gk20a.h" |
35 | #include "hw_pbdma_gk20a.h" | 35 | #include "hw_pbdma_gk20a.h" |
36 | 36 | ||
37 | static int gk20a_cde_load(struct gk20a_cde_ctx *cde_ctx, bool free_after_use); | ||
38 | |||
37 | static void gk20a_deinit_cde_img(struct gk20a_cde_ctx *cde_ctx) | 39 | static void gk20a_deinit_cde_img(struct gk20a_cde_ctx *cde_ctx) |
38 | { | 40 | { |
39 | struct device *dev = &cde_ctx->pdev->dev; | 41 | struct device *dev = &cde_ctx->pdev->dev; |
@@ -589,10 +591,11 @@ static int gk20a_cde_execute_buffer(struct gk20a_cde_ctx *cde_ctx, | |||
589 | num_entries, flags, fence, fence_out); | 591 | num_entries, flags, fence, fence_out); |
590 | } | 592 | } |
591 | 593 | ||
592 | static struct gk20a_cde_ctx *gk20a_cde_get_context(struct gk20a_cde_app *cde_app) | 594 | static struct gk20a_cde_ctx *gk20a_cde_get_context(struct gk20a *g) |
593 | { | 595 | { |
596 | struct gk20a_cde_app *cde_app = &g->cde_app; | ||
594 | struct gk20a_cde_ctx *cde_ctx = cde_app->cde_ctx; | 597 | struct gk20a_cde_ctx *cde_ctx = cde_app->cde_ctx; |
595 | int i; | 598 | int i, ret; |
596 | 599 | ||
597 | /* try to find a jobless context */ | 600 | /* try to find a jobless context */ |
598 | 601 | ||
@@ -608,10 +611,22 @@ static struct gk20a_cde_ctx *gk20a_cde_get_context(struct gk20a_cde_app *cde_app | |||
608 | return cde_ctx; | 611 | return cde_ctx; |
609 | } | 612 | } |
610 | 613 | ||
611 | /* pick just the next cde context, hopefully somewhat in order */ | 614 | /* could not find a free one, so allocate dynamically */ |
612 | cde_ctx = cde_app->cde_ctx + cde_app->cde_ctx_ptr; | 615 | |
613 | cde_app->cde_ctx_ptr = (cde_app->cde_ctx_ptr + 1) % | 616 | gk20a_warn(&g->dev->dev, "cde: no free contexts, allocating temporary"); |
614 | ARRAY_SIZE(cde_app->cde_ctx); | 617 | |
618 | cde_ctx = kzalloc(sizeof(*cde_ctx), GFP_KERNEL); | ||
619 | if (!cde_ctx) | ||
620 | return ERR_PTR(-ENOMEM); | ||
621 | |||
622 | cde_ctx->g = g; | ||
623 | cde_ctx->pdev = g->dev; | ||
624 | |||
625 | ret = gk20a_cde_load(cde_ctx, true); | ||
626 | if (ret) { | ||
627 | gk20a_err(&g->dev->dev, "cde: cde load failed on temporary"); | ||
628 | return ERR_PTR(ret); | ||
629 | } | ||
615 | 630 | ||
616 | return cde_ctx; | 631 | return cde_ctx; |
617 | } | 632 | } |
@@ -637,7 +652,9 @@ int gk20a_cde_convert(struct gk20a *g, | |||
637 | 652 | ||
638 | mutex_lock(&cde_app->mutex); | 653 | mutex_lock(&cde_app->mutex); |
639 | 654 | ||
640 | cde_ctx = gk20a_cde_get_context(cde_app); | 655 | cde_ctx = gk20a_cde_get_context(g); |
656 | if (IS_ERR(cde_ctx)) | ||
657 | return PTR_ERR(cde_ctx); | ||
641 | 658 | ||
642 | /* First, map the buffers to local va */ | 659 | /* First, map the buffers to local va */ |
643 | 660 | ||
@@ -747,7 +764,32 @@ exit_unlock: | |||
747 | return err; | 764 | return err; |
748 | } | 765 | } |
749 | 766 | ||
750 | int gk20a_cde_load(struct gk20a_cde_ctx *cde_ctx) | 767 | static void gk20a_free_ctx_cb(struct channel_gk20a *ch, void *data) |
768 | { | ||
769 | struct gk20a_cde_ctx *cde_ctx = data; | ||
770 | bool empty; | ||
771 | int err; | ||
772 | |||
773 | mutex_lock(&ch->jobs_lock); | ||
774 | empty = list_empty(&ch->jobs); | ||
775 | mutex_unlock(&ch->jobs_lock); | ||
776 | |||
777 | if (!empty) | ||
778 | return; | ||
779 | |||
780 | /* this should fail only when shutting down the whole device */ | ||
781 | err = gk20a_busy(cde_ctx->pdev); | ||
782 | if (WARN(err, "gk20a cde: cannot set gk20a on, not freeing channel" | ||
783 | ", leaking memory")) | ||
784 | return; | ||
785 | |||
786 | gk20a_cde_remove(cde_ctx); | ||
787 | gk20a_idle(cde_ctx->pdev); | ||
788 | |||
789 | kfree(cde_ctx); | ||
790 | } | ||
791 | |||
792 | static int gk20a_cde_load(struct gk20a_cde_ctx *cde_ctx, bool free_after_use) | ||
751 | { | 793 | { |
752 | struct gk20a *g = cde_ctx->g; | 794 | struct gk20a *g = cde_ctx->g; |
753 | const struct firmware *img; | 795 | const struct firmware *img; |
@@ -762,7 +804,10 @@ int gk20a_cde_load(struct gk20a_cde_ctx *cde_ctx) | |||
762 | return -ENOSYS; | 804 | return -ENOSYS; |
763 | } | 805 | } |
764 | 806 | ||
765 | ch = gk20a_open_new_channel(g); | 807 | if (free_after_use) |
808 | ch = gk20a_open_new_channel_with_cb(g, gk20a_free_ctx_cb, cde_ctx); | ||
809 | else | ||
810 | ch = gk20a_open_new_channel(g); | ||
766 | if (!ch) { | 811 | if (!ch) { |
767 | gk20a_warn(&cde_ctx->pdev->dev, "cde: gk20a channel not available"); | 812 | gk20a_warn(&cde_ctx->pdev->dev, "cde: gk20a channel not available"); |
768 | err = -ENOMEM; | 813 | err = -ENOMEM; |
@@ -852,10 +897,9 @@ int gk20a_cde_reload(struct gk20a *g) | |||
852 | mutex_lock(&cde_app->mutex); | 897 | mutex_lock(&cde_app->mutex); |
853 | for (i = 0; i < ARRAY_SIZE(cde_app->cde_ctx); i++, cde_ctx++) { | 898 | for (i = 0; i < ARRAY_SIZE(cde_app->cde_ctx); i++, cde_ctx++) { |
854 | gk20a_cde_remove(cde_ctx); | 899 | gk20a_cde_remove(cde_ctx); |
855 | err = gk20a_cde_load(cde_ctx); | 900 | err = gk20a_cde_load(cde_ctx, false); |
856 | } | 901 | } |
857 | 902 | ||
858 | cde_app->cde_ctx_ptr = 0; | ||
859 | mutex_unlock(&cde_app->mutex); | 903 | mutex_unlock(&cde_app->mutex); |
860 | 904 | ||
861 | gk20a_idle(g->dev); | 905 | gk20a_idle(g->dev); |
@@ -877,7 +921,7 @@ int gk20a_init_cde_support(struct gk20a *g) | |||
877 | for (i = 0; i < ARRAY_SIZE(cde_app->cde_ctx); i++, cde_ctx++) { | 921 | for (i = 0; i < ARRAY_SIZE(cde_app->cde_ctx); i++, cde_ctx++) { |
878 | cde_ctx->g = g; | 922 | cde_ctx->g = g; |
879 | cde_ctx->pdev = g->dev; | 923 | cde_ctx->pdev = g->dev; |
880 | ret = gk20a_cde_load(cde_ctx); | 924 | ret = gk20a_cde_load(cde_ctx, false); |
881 | if (ret) | 925 | if (ret) |
882 | goto err_init_instance; | 926 | goto err_init_instance; |
883 | } | 927 | } |
@@ -885,7 +929,6 @@ int gk20a_init_cde_support(struct gk20a *g) | |||
885 | /* take shadow to the vm for general usage */ | 929 | /* take shadow to the vm for general usage */ |
886 | cde_app->vm = cde_app->cde_ctx->vm; | 930 | cde_app->vm = cde_app->cde_ctx->vm; |
887 | 931 | ||
888 | cde_app->cde_ctx_ptr = 0; | ||
889 | cde_app->initialised = true; | 932 | cde_app->initialised = true; |
890 | mutex_unlock(&cde_app->mutex); | 933 | mutex_unlock(&cde_app->mutex); |
891 | 934 | ||
diff --git a/drivers/gpu/nvgpu/gk20a/cde_gk20a.h b/drivers/gpu/nvgpu/gk20a/cde_gk20a.h index b93e56c8..e4d4659d 100644 --- a/drivers/gpu/nvgpu/gk20a/cde_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/cde_gk20a.h | |||
@@ -250,7 +250,6 @@ struct gk20a_cde_app { | |||
250 | struct vm_gk20a *vm; | 250 | struct vm_gk20a *vm; |
251 | 251 | ||
252 | struct gk20a_cde_ctx cde_ctx[NUM_CDE_CONTEXTS]; | 252 | struct gk20a_cde_ctx cde_ctx[NUM_CDE_CONTEXTS]; |
253 | int cde_ctx_ptr; | ||
254 | 253 | ||
255 | u32 shader_parameter; | 254 | u32 shader_parameter; |
256 | }; | 255 | }; |