summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/nvgpu/common/linux/comptags.c26
-rw-r--r--drivers/gpu/nvgpu/common/mm/vm.c71
-rw-r--r--drivers/gpu/nvgpu/include/nvgpu/comptags.h25
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
42int gk20a_alloc_comptags(struct gk20a *g, 42int 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
90void 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
38struct gk20a_comptag_allocator { 43struct 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 */
66int gk20a_alloc_comptags(struct gk20a *g, 71int 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);
70void gk20a_get_comptags(struct nvgpu_os_buffer *buf, 76void gk20a_get_comptags(struct nvgpu_os_buffer *buf,
71 struct gk20a_comptags *comptags); 77 struct gk20a_comptags *comptags);
72 78void gk20a_mark_comptags_cleared(struct nvgpu_os_buffer *buf);
73
74 79
75#endif 80#endif