diff options
author | Sami Kiminki <skiminki@nvidia.com> | 2017-11-13 06:52:29 -0500 |
---|---|---|
committer | mobile promotions <svcmobile_promotions@nvidia.com> | 2017-11-15 16:26:02 -0500 |
commit | 23396c58db7e9d9c974bb3334a159aad960afc3e (patch) | |
tree | 21600214cdd1737075b73354b40fca7fbe97f93e | |
parent | 434385ca54053b13ac06a5f11cb7564d6740f02d (diff) |
gpu: nvgpu: Simplify compbits alloc and add needs_clear
Simplify compbits alloc by making the alloc function re-callable for
the buffer, and making it return the comptags info. This simplifies
the calling code: alloc_or_get vs. get + alloc + get again.
Add tracking whether the allocated compbits need clearing before they
can be used in PTEs. We do this, since clearing is part of the gmmu
map call on vgpu, which can fail.
Bug 1902982
Change-Id: Ic4ab8d326910443b128e82491d302a1f49120f5b
Signed-off-by: Sami Kiminki <skiminki@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1597130
GVS: Gerrit_Virtual_Submit
Reviewed-by: Alex Waterman <alexw@nvidia.com>
Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com>
Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
-rw-r--r-- | drivers/gpu/nvgpu/common/linux/comptags.c | 26 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/common/mm/vm.c | 71 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/include/nvgpu/comptags.h | 25 |
3 files changed, 67 insertions, 55 deletions
diff --git a/drivers/gpu/nvgpu/common/linux/comptags.c b/drivers/gpu/nvgpu/common/linux/comptags.c index 92e8aa3e..4a96e07b 100644 --- a/drivers/gpu/nvgpu/common/linux/comptags.c +++ b/drivers/gpu/nvgpu/common/linux/comptags.c | |||
@@ -39,10 +39,11 @@ void gk20a_get_comptags(struct nvgpu_os_buffer *buf, | |||
39 | *comptags = priv->comptags; | 39 | *comptags = priv->comptags; |
40 | } | 40 | } |
41 | 41 | ||
42 | int gk20a_alloc_comptags(struct gk20a *g, | 42 | int gk20a_alloc_or_get_comptags(struct gk20a *g, |
43 | struct nvgpu_os_buffer *buf, | 43 | struct nvgpu_os_buffer *buf, |
44 | struct gk20a_comptag_allocator *allocator, | 44 | struct gk20a_comptag_allocator *allocator, |
45 | u32 lines) | 45 | u32 lines, |
46 | struct gk20a_comptags *comptags) | ||
46 | { | 47 | { |
47 | struct gk20a_dmabuf_priv *priv = dma_buf_get_drvdata(buf->dmabuf, | 48 | struct gk20a_dmabuf_priv *priv = dma_buf_get_drvdata(buf->dmabuf, |
48 | buf->dev); | 49 | buf->dev); |
@@ -55,15 +56,23 @@ int gk20a_alloc_comptags(struct gk20a *g, | |||
55 | if (!lines) | 56 | if (!lines) |
56 | return -EINVAL; | 57 | return -EINVAL; |
57 | 58 | ||
59 | if (priv->comptags.allocated) { | ||
60 | /* already allocated */ | ||
61 | *comptags = priv->comptags; | ||
62 | return 0; | ||
63 | } | ||
64 | |||
58 | /* store the allocator so we can use it when we free the ctags */ | 65 | /* store the allocator so we can use it when we free the ctags */ |
59 | priv->comptag_allocator = allocator; | 66 | priv->comptag_allocator = allocator; |
60 | err = gk20a_comptaglines_alloc(allocator, &offset, lines); | 67 | err = gk20a_comptaglines_alloc(allocator, &offset, lines); |
61 | if (!err) { | 68 | if (!err) { |
62 | priv->comptags.offset = offset; | 69 | priv->comptags.offset = offset; |
63 | priv->comptags.lines = lines; | 70 | priv->comptags.lines = lines; |
71 | priv->comptags.needs_clear = true; | ||
64 | } else { | 72 | } else { |
65 | priv->comptags.offset = 0; | 73 | priv->comptags.offset = 0; |
66 | priv->comptags.lines = 0; | 74 | priv->comptags.lines = 0; |
75 | priv->comptags.needs_clear = false; | ||
67 | } | 76 | } |
68 | 77 | ||
69 | /* | 78 | /* |
@@ -74,5 +83,14 @@ int gk20a_alloc_comptags(struct gk20a *g, | |||
74 | */ | 83 | */ |
75 | priv->comptags.allocated = true; | 84 | priv->comptags.allocated = true; |
76 | 85 | ||
86 | *comptags = priv->comptags; | ||
77 | return 0; | 87 | return 0; |
78 | } | 88 | } |
89 | |||
90 | void gk20a_mark_comptags_cleared(struct nvgpu_os_buffer *buf) | ||
91 | { | ||
92 | struct gk20a_dmabuf_priv *priv = dma_buf_get_drvdata(buf->dmabuf, | ||
93 | buf->dev); | ||
94 | if (priv) | ||
95 | priv->comptags.needs_clear = false; | ||
96 | } | ||
diff --git a/drivers/gpu/nvgpu/common/mm/vm.c b/drivers/gpu/nvgpu/common/mm/vm.c index be7e4207..7a451956 100644 --- a/drivers/gpu/nvgpu/common/mm/vm.c +++ b/drivers/gpu/nvgpu/common/mm/vm.c | |||
@@ -857,53 +857,39 @@ struct nvgpu_mapped_buf *nvgpu_vm_map(struct vm_gk20a *vm, | |||
857 | struct gk20a_comptags comptags = { 0 }; | 857 | struct gk20a_comptags comptags = { 0 }; |
858 | 858 | ||
859 | /* | 859 | /* |
860 | * Get the comptags state | 860 | * Get the comptags state, alloc if necessary |
861 | */ | 861 | */ |
862 | gk20a_get_comptags(os_buf, &comptags); | 862 | err = gk20a_alloc_or_get_comptags(g, os_buf, |
863 | &g->gr.comp_tags, | ||
864 | binfo.ctag_lines, &comptags); | ||
865 | if (err) { | ||
866 | /* | ||
867 | * This is an irrecoverable failure and we need to | ||
868 | * abort. In particular, it is not safe to proceed with | ||
869 | * the incompressible fallback, since we cannot not mark | ||
870 | * our alloc failure anywere. Later we would retry | ||
871 | * allocation and break compressible map aliasing. | ||
872 | */ | ||
873 | nvgpu_err(g, "Error %d setting up comptags", err); | ||
874 | goto clean_up; | ||
875 | } | ||
863 | 876 | ||
864 | /* | 877 | /* |
865 | * Allocate if not yet allocated | 878 | * Newly allocated comptags needs to be cleared |
866 | */ | 879 | */ |
867 | if (!comptags.allocated) { | 880 | if (comptags.needs_clear) { |
868 | err = gk20a_alloc_comptags(g, os_buf, | 881 | if (g->ops.ltc.cbc_ctrl) { |
869 | &g->gr.comp_tags, | 882 | g->ops.ltc.cbc_ctrl( |
870 | binfo.ctag_lines); | 883 | g, gk20a_cbc_op_clear, |
871 | if (err) { | 884 | comptags.offset, |
885 | (comptags.offset + | ||
886 | comptags.lines - 1)); | ||
887 | gk20a_mark_comptags_cleared(os_buf); | ||
888 | } else { | ||
872 | /* | 889 | /* |
873 | * This is an irrecoverable failure and we need | 890 | * Cleared as part of gmmu map |
874 | * to abort. In particular, it is not safe to | ||
875 | * proceed with incompressible fallback, since | ||
876 | * we could not mark our alloc failure | ||
877 | * anywere. Later we would retry allocation and | ||
878 | * break compressible map aliasing. | ||
879 | */ | 891 | */ |
880 | nvgpu_err(g, | 892 | clear_ctags = true; |
881 | "Error %d setting up comptags", err); | ||
882 | goto clean_up; | ||
883 | } | ||
884 | |||
885 | /* | ||
886 | * Refresh comptags state after alloc. Field | ||
887 | * comptags.lines will be 0 if alloc failed. | ||
888 | */ | ||
889 | gk20a_get_comptags(os_buf, &comptags); | ||
890 | |||
891 | /* | ||
892 | * Newly allocated comptags needs to be cleared | ||
893 | */ | ||
894 | if (comptags.lines) { | ||
895 | if (g->ops.ltc.cbc_ctrl) | ||
896 | g->ops.ltc.cbc_ctrl( | ||
897 | g, gk20a_cbc_op_clear, | ||
898 | comptags.offset, | ||
899 | (comptags.offset + | ||
900 | comptags.lines - 1)); | ||
901 | else | ||
902 | /* | ||
903 | * The comptags will be cleared as part | ||
904 | * of mapping (vgpu) | ||
905 | */ | ||
906 | clear_ctags = true; | ||
907 | } | 893 | } |
908 | } | 894 | } |
909 | 895 | ||
@@ -959,6 +945,9 @@ struct nvgpu_mapped_buf *nvgpu_vm_map(struct vm_gk20a *vm, | |||
959 | goto clean_up; | 945 | goto clean_up; |
960 | } | 946 | } |
961 | 947 | ||
948 | if (clear_ctags) | ||
949 | gk20a_mark_comptags_cleared(os_buf); | ||
950 | |||
962 | nvgpu_init_list_node(&mapped_buffer->buffer_list); | 951 | nvgpu_init_list_node(&mapped_buffer->buffer_list); |
963 | nvgpu_ref_init(&mapped_buffer->ref); | 952 | nvgpu_ref_init(&mapped_buffer->ref); |
964 | mapped_buffer->addr = map_addr; | 953 | mapped_buffer->addr = map_addr; |
diff --git a/drivers/gpu/nvgpu/include/nvgpu/comptags.h b/drivers/gpu/nvgpu/include/nvgpu/comptags.h index 2d9f034a..41a918b5 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/comptags.h +++ b/drivers/gpu/nvgpu/include/nvgpu/comptags.h | |||
@@ -27,12 +27,17 @@ struct gk20a_comptags { | |||
27 | u32 lines; | 27 | u32 lines; |
28 | 28 | ||
29 | /* | 29 | /* |
30 | * This signals whether allocation has been attempted. Observe | 30 | * This signals whether allocation has been attempted. Observe 'lines' |
31 | * 'lines' to see whether comptags were actually allocated. We | 31 | * to see whether the comptags were actually allocated. We try alloc |
32 | * try alloc only once per buffer in order not to break | 32 | * only once per buffer in order not to break multiple compressible-kind |
33 | * multiple compressible-kind mappings. | 33 | * mappings. |
34 | */ | 34 | */ |
35 | bool allocated; | 35 | bool allocated; |
36 | |||
37 | /* | ||
38 | * Do comptags need to be cleared before mapping? | ||
39 | */ | ||
40 | bool needs_clear; | ||
36 | }; | 41 | }; |
37 | 42 | ||
38 | struct gk20a_comptag_allocator { | 43 | struct gk20a_comptag_allocator { |
@@ -63,13 +68,13 @@ void gk20a_comptaglines_free(struct gk20a_comptag_allocator *allocator, | |||
63 | * Defined by OS specific code since comptags are stored in a highly OS specific | 68 | * Defined by OS specific code since comptags are stored in a highly OS specific |
64 | * way. | 69 | * way. |
65 | */ | 70 | */ |
66 | int gk20a_alloc_comptags(struct gk20a *g, | 71 | int gk20a_alloc_or_get_comptags(struct gk20a *g, |
67 | struct nvgpu_os_buffer *buf, | 72 | struct nvgpu_os_buffer *buf, |
68 | struct gk20a_comptag_allocator *allocator, | 73 | struct gk20a_comptag_allocator *allocator, |
69 | u32 lines); | 74 | u32 lines, |
75 | struct gk20a_comptags *comptags); | ||
70 | void gk20a_get_comptags(struct nvgpu_os_buffer *buf, | 76 | void gk20a_get_comptags(struct nvgpu_os_buffer *buf, |
71 | struct gk20a_comptags *comptags); | 77 | struct gk20a_comptags *comptags); |
72 | 78 | void gk20a_mark_comptags_cleared(struct nvgpu_os_buffer *buf); | |
73 | |||
74 | 79 | ||
75 | #endif | 80 | #endif |