diff options
Diffstat (limited to 'drivers')
-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 |