diff options
author | Christoph Bumiller <e0425955@student.tuwien.ac.at> | 2013-03-27 17:16:53 -0400 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2013-04-26 01:37:40 -0400 |
commit | e30441adb91b020044f257c5c8e41022f3406ba1 (patch) | |
tree | ed9aaaa9a0aeb74eeaef783b4fd531269d3396ae | |
parent | de7b7d59d54852c9544a9e4fa7af719511fb5366 (diff) |
drm/nvc0-/ltcg: implement VRAM compression
Signed-off-by: Christoph Bumiller <e0425955@student.tuwien.ac.at>
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r-- | drivers/gpu/drm/nouveau/core/include/subdev/ltcg.h | 7 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c | 55 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c | 129 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c | 58 |
4 files changed, 220 insertions, 29 deletions
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/ltcg.h b/drivers/gpu/drm/nouveau/core/include/subdev/ltcg.h index f351f63bc654..a1985ed3d58d 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/ltcg.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/ltcg.h | |||
@@ -4,8 +4,15 @@ | |||
4 | #include <core/subdev.h> | 4 | #include <core/subdev.h> |
5 | #include <core/device.h> | 5 | #include <core/device.h> |
6 | 6 | ||
7 | struct nouveau_mm_node; | ||
8 | |||
7 | struct nouveau_ltcg { | 9 | struct nouveau_ltcg { |
8 | struct nouveau_subdev base; | 10 | struct nouveau_subdev base; |
11 | |||
12 | int (*tags_alloc)(struct nouveau_ltcg *, u32 count, | ||
13 | struct nouveau_mm_node **); | ||
14 | void (*tags_free)(struct nouveau_ltcg *, struct nouveau_mm_node **); | ||
15 | void (*tags_clear)(struct nouveau_ltcg *, u32 first, u32 count); | ||
9 | }; | 16 | }; |
10 | 17 | ||
11 | static inline struct nouveau_ltcg * | 18 | static inline struct nouveau_ltcg * |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c index 3b2ddc65bd48..86ad59203c8b 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c | |||
@@ -23,6 +23,7 @@ | |||
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include <subdev/fb.h> | 25 | #include <subdev/fb.h> |
26 | #include <subdev/ltcg.h> | ||
26 | #include <subdev/bios.h> | 27 | #include <subdev/bios.h> |
27 | 28 | ||
28 | struct nvc0_fb_priv { | 29 | struct nvc0_fb_priv { |
@@ -31,34 +32,14 @@ struct nvc0_fb_priv { | |||
31 | dma_addr_t r100c10; | 32 | dma_addr_t r100c10; |
32 | }; | 33 | }; |
33 | 34 | ||
34 | /* 0 = unsupported | 35 | extern const u8 nvc0_pte_storage_type_map[256]; |
35 | * 1 = non-compressed | 36 | |
36 | * 3 = compressed | ||
37 | */ | ||
38 | static const u8 types[256] = { | ||
39 | 1, 1, 3, 3, 3, 3, 0, 3, 3, 3, 3, 0, 0, 0, 0, 0, | ||
40 | 0, 1, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 0, 0, 0, 0, | ||
41 | 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, | ||
42 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, | ||
43 | 3, 3, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
44 | 0, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
45 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
46 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, | ||
47 | 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 1, 1, 1, 1, 0, | ||
48 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
49 | 0, 0, 0, 3, 3, 3, 3, 1, 1, 1, 1, 0, 0, 0, 0, 0, | ||
50 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, | ||
51 | 3, 3, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, | ||
52 | 3, 3, 0, 0, 0, 0, 0, 0, 3, 0, 0, 3, 0, 3, 0, 3, | ||
53 | 3, 0, 3, 3, 3, 3, 3, 0, 0, 3, 0, 3, 0, 3, 3, 0, | ||
54 | 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 1, 1, 0 | ||
55 | }; | ||
56 | 37 | ||
57 | static bool | 38 | static bool |
58 | nvc0_fb_memtype_valid(struct nouveau_fb *pfb, u32 tile_flags) | 39 | nvc0_fb_memtype_valid(struct nouveau_fb *pfb, u32 tile_flags) |
59 | { | 40 | { |
60 | u8 memtype = (tile_flags & 0x0000ff00) >> 8; | 41 | u8 memtype = (tile_flags & 0x0000ff00) >> 8; |
61 | return likely((types[memtype] == 1)); | 42 | return likely((nvc0_pte_storage_type_map[memtype] != 0xff)); |
62 | } | 43 | } |
63 | 44 | ||
64 | static int | 45 | static int |
@@ -130,6 +111,7 @@ nvc0_fb_vram_new(struct nouveau_fb *pfb, u64 size, u32 align, u32 ncmin, | |||
130 | int type = (memtype & 0x0ff); | 111 | int type = (memtype & 0x0ff); |
131 | int back = (memtype & 0x800); | 112 | int back = (memtype & 0x800); |
132 | int ret; | 113 | int ret; |
114 | const bool comp = nvc0_pte_storage_type_map[type] != type; | ||
133 | 115 | ||
134 | size >>= 12; | 116 | size >>= 12; |
135 | align >>= 12; | 117 | align >>= 12; |
@@ -142,10 +124,22 @@ nvc0_fb_vram_new(struct nouveau_fb *pfb, u64 size, u32 align, u32 ncmin, | |||
142 | return -ENOMEM; | 124 | return -ENOMEM; |
143 | 125 | ||
144 | INIT_LIST_HEAD(&mem->regions); | 126 | INIT_LIST_HEAD(&mem->regions); |
145 | mem->memtype = type; | ||
146 | mem->size = size; | 127 | mem->size = size; |
147 | 128 | ||
148 | mutex_lock(&pfb->base.mutex); | 129 | mutex_lock(&pfb->base.mutex); |
130 | if (comp) { | ||
131 | struct nouveau_ltcg *ltcg = nouveau_ltcg(pfb->base.base.parent); | ||
132 | |||
133 | /* compression only works with lpages */ | ||
134 | if (align == (1 << (17 - 12))) { | ||
135 | int n = size >> 5; | ||
136 | ltcg->tags_alloc(ltcg, n, &mem->tag); | ||
137 | } | ||
138 | if (unlikely(!mem->tag)) | ||
139 | type = nvc0_pte_storage_type_map[type]; | ||
140 | } | ||
141 | mem->memtype = type; | ||
142 | |||
149 | do { | 143 | do { |
150 | if (back) | 144 | if (back) |
151 | ret = nouveau_mm_tail(mm, 1, size, ncmin, align, &r); | 145 | ret = nouveau_mm_tail(mm, 1, size, ncmin, align, &r); |
@@ -168,6 +162,17 @@ nvc0_fb_vram_new(struct nouveau_fb *pfb, u64 size, u32 align, u32 ncmin, | |||
168 | return 0; | 162 | return 0; |
169 | } | 163 | } |
170 | 164 | ||
165 | static void | ||
166 | nvc0_fb_vram_del(struct nouveau_fb *pfb, struct nouveau_mem **pmem) | ||
167 | { | ||
168 | struct nouveau_ltcg *ltcg = nouveau_ltcg(pfb->base.base.parent); | ||
169 | |||
170 | if ((*pmem)->tag) | ||
171 | ltcg->tags_free(ltcg, &(*pmem)->tag); | ||
172 | |||
173 | nv50_fb_vram_del(pfb, pmem); | ||
174 | } | ||
175 | |||
171 | static int | 176 | static int |
172 | nvc0_fb_init(struct nouveau_object *object) | 177 | nvc0_fb_init(struct nouveau_object *object) |
173 | { | 178 | { |
@@ -215,7 +220,7 @@ nvc0_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
215 | priv->base.memtype_valid = nvc0_fb_memtype_valid; | 220 | priv->base.memtype_valid = nvc0_fb_memtype_valid; |
216 | priv->base.ram.init = nvc0_fb_vram_init; | 221 | priv->base.ram.init = nvc0_fb_vram_init; |
217 | priv->base.ram.get = nvc0_fb_vram_new; | 222 | priv->base.ram.get = nvc0_fb_vram_new; |
218 | priv->base.ram.put = nv50_fb_vram_del; | 223 | priv->base.ram.put = nvc0_fb_vram_del; |
219 | 224 | ||
220 | priv->r100c10_page = alloc_page(GFP_KERNEL | __GFP_ZERO); | 225 | priv->r100c10_page = alloc_page(GFP_KERNEL | __GFP_ZERO); |
221 | if (priv->r100c10_page) { | 226 | if (priv->r100c10_page) { |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c index 078a2b9d6bd6..a529563b5f8c 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c | |||
@@ -23,10 +23,17 @@ | |||
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include <subdev/ltcg.h> | 25 | #include <subdev/ltcg.h> |
26 | #include <subdev/fb.h> | ||
27 | #include <subdev/timer.h> | ||
26 | 28 | ||
27 | struct nvc0_ltcg_priv { | 29 | struct nvc0_ltcg_priv { |
28 | struct nouveau_ltcg base; | 30 | struct nouveau_ltcg base; |
31 | u32 part_nr; | ||
32 | u32 part_mask; | ||
29 | u32 subp_nr; | 33 | u32 subp_nr; |
34 | struct nouveau_mm tags; | ||
35 | u32 num_tags; | ||
36 | struct nouveau_mm_node *tag_ram; | ||
30 | }; | 37 | }; |
31 | 38 | ||
32 | static void | 39 | static void |
@@ -62,11 +69,104 @@ nvc0_ltcg_intr(struct nouveau_subdev *subdev) | |||
62 | } | 69 | } |
63 | 70 | ||
64 | static int | 71 | static int |
72 | nvc0_ltcg_tags_alloc(struct nouveau_ltcg *ltcg, u32 n, | ||
73 | struct nouveau_mm_node **pnode) | ||
74 | { | ||
75 | struct nvc0_ltcg_priv *priv = (struct nvc0_ltcg_priv *)ltcg; | ||
76 | int ret; | ||
77 | |||
78 | ret = nouveau_mm_head(&priv->tags, 1, n, n, 1, pnode); | ||
79 | if (ret) | ||
80 | *pnode = NULL; | ||
81 | |||
82 | return ret; | ||
83 | } | ||
84 | |||
85 | static void | ||
86 | nvc0_ltcg_tags_free(struct nouveau_ltcg *ltcg, struct nouveau_mm_node **pnode) | ||
87 | { | ||
88 | struct nvc0_ltcg_priv *priv = (struct nvc0_ltcg_priv *)ltcg; | ||
89 | |||
90 | nouveau_mm_free(&priv->tags, pnode); | ||
91 | } | ||
92 | |||
93 | static void | ||
94 | nvc0_ltcg_tags_clear(struct nouveau_ltcg *ltcg, u32 first, u32 count) | ||
95 | { | ||
96 | struct nvc0_ltcg_priv *priv = (struct nvc0_ltcg_priv *)ltcg; | ||
97 | u32 last = first + count - 1; | ||
98 | int p, i; | ||
99 | |||
100 | BUG_ON((first > last) || (last >= priv->num_tags)); | ||
101 | |||
102 | nv_wr32(priv, 0x17e8cc, first); | ||
103 | nv_wr32(priv, 0x17e8d0, last); | ||
104 | nv_wr32(priv, 0x17e8c8, 0x4); /* trigger clear */ | ||
105 | |||
106 | /* wait until it's finished with clearing */ | ||
107 | for (p = 0; p < priv->part_nr; ++p) { | ||
108 | if (!(priv->part_mask & (1 << p))) | ||
109 | continue; | ||
110 | for (i = 0; i < priv->subp_nr; ++i) | ||
111 | nv_wait(priv, 0x1410c8 + p * 0x2000 + i * 0x400, ~0, 0); | ||
112 | } | ||
113 | } | ||
114 | |||
115 | /* TODO: Figure out tag memory details and drop the over-cautious allocation. | ||
116 | */ | ||
117 | static int | ||
118 | nvc0_ltcg_init_tag_ram(struct nouveau_fb *pfb, struct nvc0_ltcg_priv *priv) | ||
119 | { | ||
120 | u32 tag_size, tag_margin, tag_align; | ||
121 | int ret; | ||
122 | |||
123 | nv_wr32(priv, 0x17e8d8, priv->part_nr); | ||
124 | |||
125 | /* tags for 1/4 of VRAM should be enough (8192/4 per GiB of VRAM) */ | ||
126 | priv->num_tags = (pfb->ram.size >> 17) / 4; | ||
127 | if (priv->num_tags > (1 << 17)) | ||
128 | priv->num_tags = 1 << 17; /* we have 17 bits in PTE */ | ||
129 | priv->num_tags = (priv->num_tags + 63) & ~63; /* round up to 64 */ | ||
130 | |||
131 | tag_align = priv->part_nr * 0x800; | ||
132 | tag_margin = (tag_align < 0x6000) ? 0x6000 : tag_align; | ||
133 | |||
134 | /* 4 part 4 sub: 0x2000 bytes for 56 tags */ | ||
135 | /* 3 part 4 sub: 0x6000 bytes for 168 tags */ | ||
136 | /* | ||
137 | * About 147 bytes per tag. Let's be safe and allocate x2, which makes | ||
138 | * 0x4980 bytes for 64 tags, and round up to 0x6000 bytes for 64 tags. | ||
139 | * | ||
140 | * For 4 GiB of memory we'll have 8192 tags which makes 3 MiB, < 0.1 %. | ||
141 | */ | ||
142 | tag_size = (priv->num_tags / 64) * 0x6000 + tag_margin; | ||
143 | tag_size += tag_align; | ||
144 | tag_size = (tag_size + 0xfff) >> 12; /* round up */ | ||
145 | |||
146 | ret = nouveau_mm_tail(&pfb->vram, 0, tag_size, tag_size, 1, | ||
147 | &priv->tag_ram); | ||
148 | if (ret) { | ||
149 | priv->num_tags = 0; | ||
150 | } else { | ||
151 | u64 tag_base = (priv->tag_ram->offset << 12) + tag_margin; | ||
152 | |||
153 | tag_base += tag_align - 1; | ||
154 | tag_base /= tag_align; | ||
155 | |||
156 | nv_wr32(priv, 0x17e8d4, tag_base); | ||
157 | } | ||
158 | ret = nouveau_mm_init(&priv->tags, 0, priv->num_tags, 1); | ||
159 | |||
160 | return ret; | ||
161 | } | ||
162 | |||
163 | static int | ||
65 | nvc0_ltcg_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | 164 | nvc0_ltcg_ctor(struct nouveau_object *parent, struct nouveau_object *engine, |
66 | struct nouveau_oclass *oclass, void *data, u32 size, | 165 | struct nouveau_oclass *oclass, void *data, u32 size, |
67 | struct nouveau_object **pobject) | 166 | struct nouveau_object **pobject) |
68 | { | 167 | { |
69 | struct nvc0_ltcg_priv *priv; | 168 | struct nvc0_ltcg_priv *priv; |
169 | struct nouveau_fb *pfb = nouveau_fb(parent); | ||
70 | int ret; | 170 | int ret; |
71 | 171 | ||
72 | ret = nouveau_ltcg_create(parent, engine, oclass, &priv); | 172 | ret = nouveau_ltcg_create(parent, engine, oclass, &priv); |
@@ -74,19 +174,44 @@ nvc0_ltcg_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
74 | if (ret) | 174 | if (ret) |
75 | return ret; | 175 | return ret; |
76 | 176 | ||
77 | priv->subp_nr = nv_rd32(priv, 0x17e8dc) >> 24; | 177 | priv->part_nr = nv_rd32(priv, 0x022438); |
178 | priv->part_mask = nv_rd32(priv, 0x022554); | ||
179 | |||
180 | priv->subp_nr = nv_rd32(priv, 0x17e8dc) >> 28; | ||
181 | |||
78 | nv_mask(priv, 0x17e820, 0x00100000, 0x00000000); /* INTR_EN &= ~0x10 */ | 182 | nv_mask(priv, 0x17e820, 0x00100000, 0x00000000); /* INTR_EN &= ~0x10 */ |
79 | 183 | ||
184 | ret = nvc0_ltcg_init_tag_ram(pfb, priv); | ||
185 | if (ret) | ||
186 | return ret; | ||
187 | |||
188 | priv->base.tags_alloc = nvc0_ltcg_tags_alloc; | ||
189 | priv->base.tags_free = nvc0_ltcg_tags_free; | ||
190 | priv->base.tags_clear = nvc0_ltcg_tags_clear; | ||
191 | |||
80 | nv_subdev(priv)->intr = nvc0_ltcg_intr; | 192 | nv_subdev(priv)->intr = nvc0_ltcg_intr; |
81 | return 0; | 193 | return 0; |
82 | } | 194 | } |
83 | 195 | ||
196 | static void | ||
197 | nvc0_ltcg_dtor(struct nouveau_object *object) | ||
198 | { | ||
199 | struct nouveau_ltcg *ltcg = (struct nouveau_ltcg *)object; | ||
200 | struct nvc0_ltcg_priv *priv = (struct nvc0_ltcg_priv *)ltcg; | ||
201 | struct nouveau_fb *pfb = nouveau_fb(ltcg->base.base.parent); | ||
202 | |||
203 | nouveau_mm_fini(&priv->tags); | ||
204 | nouveau_mm_free(&pfb->vram, &priv->tag_ram); | ||
205 | |||
206 | nouveau_ltcg_destroy(ltcg); | ||
207 | } | ||
208 | |||
84 | struct nouveau_oclass | 209 | struct nouveau_oclass |
85 | nvc0_ltcg_oclass = { | 210 | nvc0_ltcg_oclass = { |
86 | .handle = NV_SUBDEV(LTCG, 0xc0), | 211 | .handle = NV_SUBDEV(LTCG, 0xc0), |
87 | .ofuncs = &(struct nouveau_ofuncs) { | 212 | .ofuncs = &(struct nouveau_ofuncs) { |
88 | .ctor = nvc0_ltcg_ctor, | 213 | .ctor = nvc0_ltcg_ctor, |
89 | .dtor = _nouveau_ltcg_dtor, | 214 | .dtor = nvc0_ltcg_dtor, |
90 | .init = _nouveau_ltcg_init, | 215 | .init = _nouveau_ltcg_init, |
91 | .fini = _nouveau_ltcg_fini, | 216 | .fini = _nouveau_ltcg_fini, |
92 | }, | 217 | }, |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c index 30c61e6c2017..4c3b0a23b9d6 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nvc0.c | |||
@@ -28,12 +28,54 @@ | |||
28 | #include <subdev/timer.h> | 28 | #include <subdev/timer.h> |
29 | #include <subdev/fb.h> | 29 | #include <subdev/fb.h> |
30 | #include <subdev/vm.h> | 30 | #include <subdev/vm.h> |
31 | #include <subdev/ltcg.h> | ||
31 | 32 | ||
32 | struct nvc0_vmmgr_priv { | 33 | struct nvc0_vmmgr_priv { |
33 | struct nouveau_vmmgr base; | 34 | struct nouveau_vmmgr base; |
34 | spinlock_t lock; | 35 | spinlock_t lock; |
35 | }; | 36 | }; |
36 | 37 | ||
38 | |||
39 | /* Map from compressed to corresponding uncompressed storage type. | ||
40 | * The value 0xff represents an invalid storage type. | ||
41 | */ | ||
42 | const u8 nvc0_pte_storage_type_map[256] = | ||
43 | { | ||
44 | 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0xff, 0x01, /* 0x00 */ | ||
45 | 0x01, 0x01, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
46 | 0xff, 0x11, 0xff, 0xff, 0xff, 0xff, 0xff, 0x11, /* 0x10 */ | ||
47 | 0x11, 0x11, 0x11, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
48 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x26, 0x27, /* 0x20 */ | ||
49 | 0x28, 0x29, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
50 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x30 */ | ||
51 | 0xff, 0xff, 0x26, 0x27, 0x28, 0x29, 0x26, 0x27, | ||
52 | 0x28, 0x29, 0xff, 0xff, 0xff, 0xff, 0x46, 0xff, /* 0x40 */ | ||
53 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
54 | 0xff, 0x46, 0x46, 0x46, 0x46, 0xff, 0xff, 0xff, /* 0x50 */ | ||
55 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
56 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x60 */ | ||
57 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
58 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x70 */ | ||
59 | 0xff, 0xff, 0xff, 0x7b, 0xff, 0xff, 0xff, 0xff, | ||
60 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7b, 0x7b, /* 0x80 */ | ||
61 | 0x7b, 0x7b, 0xff, 0x8b, 0x8c, 0x8d, 0x8e, 0xff, | ||
62 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x90 */ | ||
63 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
64 | 0xff, 0xff, 0xff, 0x8b, 0x8c, 0x8d, 0x8e, 0xa7, /* 0xa0 */ | ||
65 | 0xa8, 0xa9, 0xaa, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
66 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0xb0 */ | ||
67 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa7, | ||
68 | 0xa8, 0xa9, 0xaa, 0xc3, 0xff, 0xff, 0xff, 0xff, /* 0xc0 */ | ||
69 | 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xc3, 0xc3, | ||
70 | 0xc3, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0xd0 */ | ||
71 | 0xfe, 0xff, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, | ||
72 | 0xfe, 0xff, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xff, /* 0xe0 */ | ||
73 | 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xfe, 0xff, | ||
74 | 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, /* 0xf0 */ | ||
75 | 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xfd, 0xfe, 0xff | ||
76 | }; | ||
77 | |||
78 | |||
37 | static void | 79 | static void |
38 | nvc0_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 index, | 80 | nvc0_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 index, |
39 | struct nouveau_gpuobj *pgt[2]) | 81 | struct nouveau_gpuobj *pgt[2]) |
@@ -68,10 +110,20 @@ static void | |||
68 | nvc0_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, | 110 | nvc0_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, |
69 | struct nouveau_mem *mem, u32 pte, u32 cnt, u64 phys, u64 delta) | 111 | struct nouveau_mem *mem, u32 pte, u32 cnt, u64 phys, u64 delta) |
70 | { | 112 | { |
71 | u32 next = 1 << (vma->node->type - 8); | 113 | u64 next = 1 << (vma->node->type - 8); |
72 | 114 | ||
73 | phys = nvc0_vm_addr(vma, phys, mem->memtype, 0); | 115 | phys = nvc0_vm_addr(vma, phys, mem->memtype, 0); |
74 | pte <<= 3; | 116 | pte <<= 3; |
117 | |||
118 | if (mem->tag) { | ||
119 | struct nouveau_ltcg *ltcg = | ||
120 | nouveau_ltcg(vma->vm->vmm->base.base.parent); | ||
121 | u32 tag = mem->tag->offset + (delta >> 17); | ||
122 | phys |= (u64)tag << (32 + 12); | ||
123 | next |= (u64)1 << (32 + 12); | ||
124 | ltcg->tags_clear(ltcg, tag, cnt); | ||
125 | } | ||
126 | |||
75 | while (cnt--) { | 127 | while (cnt--) { |
76 | nv_wo32(pgt, pte + 0, lower_32_bits(phys)); | 128 | nv_wo32(pgt, pte + 0, lower_32_bits(phys)); |
77 | nv_wo32(pgt, pte + 4, upper_32_bits(phys)); | 129 | nv_wo32(pgt, pte + 4, upper_32_bits(phys)); |
@@ -85,10 +137,12 @@ nvc0_vm_map_sg(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, | |||
85 | struct nouveau_mem *mem, u32 pte, u32 cnt, dma_addr_t *list) | 137 | struct nouveau_mem *mem, u32 pte, u32 cnt, dma_addr_t *list) |
86 | { | 138 | { |
87 | u32 target = (vma->access & NV_MEM_ACCESS_NOSNOOP) ? 7 : 5; | 139 | u32 target = (vma->access & NV_MEM_ACCESS_NOSNOOP) ? 7 : 5; |
140 | /* compressed storage types are invalid for system memory */ | ||
141 | u32 memtype = nvc0_pte_storage_type_map[mem->memtype & 0xff]; | ||
88 | 142 | ||
89 | pte <<= 3; | 143 | pte <<= 3; |
90 | while (cnt--) { | 144 | while (cnt--) { |
91 | u64 phys = nvc0_vm_addr(vma, *list++, mem->memtype, target); | 145 | u64 phys = nvc0_vm_addr(vma, *list++, memtype, target); |
92 | nv_wo32(pgt, pte + 0, lower_32_bits(phys)); | 146 | nv_wo32(pgt, pte + 0, lower_32_bits(phys)); |
93 | nv_wo32(pgt, pte + 4, upper_32_bits(phys)); | 147 | nv_wo32(pgt, pte + 4, upper_32_bits(phys)); |
94 | pte += 8; | 148 | pte += 8; |