aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon/r600_cs.c
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2009-09-23 02:56:27 -0400
committerDave Airlie <airlied@linux.ie>2009-09-24 23:08:18 -0400
commit513bcb4655e68706594e45dfa1d4b181500110ba (patch)
treeed457db4cfb202015866a131ad4e742503728fad /drivers/gpu/drm/radeon/r600_cs.c
parent35e4b7af21d77933abda3d41d1672589eb6c960c (diff)
drm/radeon/kms: don't require up to 64k allocations. (v2)
This avoids needing to do a kmalloc > PAGE_SIZE for the main indirect buffer chunk, it adds an accessor for all reads from the chunk and caches a single page at a time for subsequent reads. changes since v1: Use a two page pool which should be the most common case a single packet spanning > PAGE_SIZE will be hit, but I'm having trouble seeing anywhere we currently generate anything like that. hopefully proper short page copying at end added parser_error flag to set deep errors instead of having to test every ib value fetch. fixed bug in patch that went to list. Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/radeon/r600_cs.c')
-rw-r--r--drivers/gpu/drm/radeon/r600_cs.c26
1 files changed, 13 insertions, 13 deletions
diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c
index 33b89cd8743..c629b5aa4a3 100644
--- a/drivers/gpu/drm/radeon/r600_cs.c
+++ b/drivers/gpu/drm/radeon/r600_cs.c
@@ -57,7 +57,7 @@ int r600_cs_packet_parse(struct radeon_cs_parser *p,
57 idx, ib_chunk->length_dw); 57 idx, ib_chunk->length_dw);
58 return -EINVAL; 58 return -EINVAL;
59 } 59 }
60 header = ib_chunk->kdata[idx]; 60 header = radeon_get_ib_value(p, idx);
61 pkt->idx = idx; 61 pkt->idx = idx;
62 pkt->type = CP_PACKET_GET_TYPE(header); 62 pkt->type = CP_PACKET_GET_TYPE(header);
63 pkt->count = CP_PACKET_GET_COUNT(header); 63 pkt->count = CP_PACKET_GET_COUNT(header);
@@ -98,7 +98,6 @@ int r600_cs_packet_parse(struct radeon_cs_parser *p,
98static int r600_cs_packet_next_reloc_mm(struct radeon_cs_parser *p, 98static int r600_cs_packet_next_reloc_mm(struct radeon_cs_parser *p,
99 struct radeon_cs_reloc **cs_reloc) 99 struct radeon_cs_reloc **cs_reloc)
100{ 100{
101 struct radeon_cs_chunk *ib_chunk;
102 struct radeon_cs_chunk *relocs_chunk; 101 struct radeon_cs_chunk *relocs_chunk;
103 struct radeon_cs_packet p3reloc; 102 struct radeon_cs_packet p3reloc;
104 unsigned idx; 103 unsigned idx;
@@ -109,7 +108,6 @@ static int r600_cs_packet_next_reloc_mm(struct radeon_cs_parser *p,
109 return -EINVAL; 108 return -EINVAL;
110 } 109 }
111 *cs_reloc = NULL; 110 *cs_reloc = NULL;
112 ib_chunk = &p->chunks[p->chunk_ib_idx];
113 relocs_chunk = &p->chunks[p->chunk_relocs_idx]; 111 relocs_chunk = &p->chunks[p->chunk_relocs_idx];
114 r = r600_cs_packet_parse(p, &p3reloc, p->idx); 112 r = r600_cs_packet_parse(p, &p3reloc, p->idx);
115 if (r) { 113 if (r) {
@@ -121,7 +119,7 @@ static int r600_cs_packet_next_reloc_mm(struct radeon_cs_parser *p,
121 p3reloc.idx); 119 p3reloc.idx);
122 return -EINVAL; 120 return -EINVAL;
123 } 121 }
124 idx = ib_chunk->kdata[p3reloc.idx + 1]; 122 idx = radeon_get_ib_value(p, p3reloc.idx + 1);
125 if (idx >= relocs_chunk->length_dw) { 123 if (idx >= relocs_chunk->length_dw) {
126 DRM_ERROR("Relocs at %d after relocations chunk end %d !\n", 124 DRM_ERROR("Relocs at %d after relocations chunk end %d !\n",
127 idx, relocs_chunk->length_dw); 125 idx, relocs_chunk->length_dw);
@@ -146,7 +144,6 @@ static int r600_cs_packet_next_reloc_mm(struct radeon_cs_parser *p,
146static int r600_cs_packet_next_reloc_nomm(struct radeon_cs_parser *p, 144static int r600_cs_packet_next_reloc_nomm(struct radeon_cs_parser *p,
147 struct radeon_cs_reloc **cs_reloc) 145 struct radeon_cs_reloc **cs_reloc)
148{ 146{
149 struct radeon_cs_chunk *ib_chunk;
150 struct radeon_cs_chunk *relocs_chunk; 147 struct radeon_cs_chunk *relocs_chunk;
151 struct radeon_cs_packet p3reloc; 148 struct radeon_cs_packet p3reloc;
152 unsigned idx; 149 unsigned idx;
@@ -157,7 +154,6 @@ static int r600_cs_packet_next_reloc_nomm(struct radeon_cs_parser *p,
157 return -EINVAL; 154 return -EINVAL;
158 } 155 }
159 *cs_reloc = NULL; 156 *cs_reloc = NULL;
160 ib_chunk = &p->chunks[p->chunk_ib_idx];
161 relocs_chunk = &p->chunks[p->chunk_relocs_idx]; 157 relocs_chunk = &p->chunks[p->chunk_relocs_idx];
162 r = r600_cs_packet_parse(p, &p3reloc, p->idx); 158 r = r600_cs_packet_parse(p, &p3reloc, p->idx);
163 if (r) { 159 if (r) {
@@ -169,7 +165,7 @@ static int r600_cs_packet_next_reloc_nomm(struct radeon_cs_parser *p,
169 p3reloc.idx); 165 p3reloc.idx);
170 return -EINVAL; 166 return -EINVAL;
171 } 167 }
172 idx = ib_chunk->kdata[p3reloc.idx + 1]; 168 idx = radeon_get_ib_value(p, p3reloc.idx + 1);
173 if (idx >= relocs_chunk->length_dw) { 169 if (idx >= relocs_chunk->length_dw) {
174 DRM_ERROR("Relocs at %d after relocations chunk end %d !\n", 170 DRM_ERROR("Relocs at %d after relocations chunk end %d !\n",
175 idx, relocs_chunk->length_dw); 171 idx, relocs_chunk->length_dw);
@@ -218,7 +214,6 @@ static int r600_cs_parse_packet0(struct radeon_cs_parser *p,
218static int r600_packet3_check(struct radeon_cs_parser *p, 214static int r600_packet3_check(struct radeon_cs_parser *p,
219 struct radeon_cs_packet *pkt) 215 struct radeon_cs_packet *pkt)
220{ 216{
221 struct radeon_cs_chunk *ib_chunk;
222 struct radeon_cs_reloc *reloc; 217 struct radeon_cs_reloc *reloc;
223 volatile u32 *ib; 218 volatile u32 *ib;
224 unsigned idx; 219 unsigned idx;
@@ -227,8 +222,8 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
227 int r; 222 int r;
228 223
229 ib = p->ib->ptr; 224 ib = p->ib->ptr;
230 ib_chunk = &p->chunks[p->chunk_ib_idx];
231 idx = pkt->idx + 1; 225 idx = pkt->idx + 1;
226
232 switch (pkt->opcode) { 227 switch (pkt->opcode) {
233 case PACKET3_START_3D_CMDBUF: 228 case PACKET3_START_3D_CMDBUF:
234 if (p->family >= CHIP_RV770 || pkt->count) { 229 if (p->family >= CHIP_RV770 || pkt->count) {
@@ -281,7 +276,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
281 return -EINVAL; 276 return -EINVAL;
282 } 277 }
283 /* bit 4 is reg (0) or mem (1) */ 278 /* bit 4 is reg (0) or mem (1) */
284 if (ib_chunk->kdata[idx+0] & 0x10) { 279 if (radeon_get_ib_value(p, idx) & 0x10) {
285 r = r600_cs_packet_next_reloc(p, &reloc); 280 r = r600_cs_packet_next_reloc(p, &reloc);
286 if (r) { 281 if (r) {
287 DRM_ERROR("bad WAIT_REG_MEM\n"); 282 DRM_ERROR("bad WAIT_REG_MEM\n");
@@ -297,8 +292,8 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
297 return -EINVAL; 292 return -EINVAL;
298 } 293 }
299 /* 0xffffffff/0x0 is flush all cache flag */ 294 /* 0xffffffff/0x0 is flush all cache flag */
300 if (ib_chunk->kdata[idx+1] != 0xffffffff || 295 if (radeon_get_ib_value(p, idx + 1) != 0xffffffff ||
301 ib_chunk->kdata[idx+2] != 0) { 296 radeon_get_ib_value(p, idx + 2) != 0) {
302 r = r600_cs_packet_next_reloc(p, &reloc); 297 r = r600_cs_packet_next_reloc(p, &reloc);
303 if (r) { 298 if (r) {
304 DRM_ERROR("bad SURFACE_SYNC\n"); 299 DRM_ERROR("bad SURFACE_SYNC\n");
@@ -639,7 +634,6 @@ int r600_cs_legacy(struct drm_device *dev, void *data, struct drm_file *filp,
639 * uncached). */ 634 * uncached). */
640 ib_chunk = &parser.chunks[parser.chunk_ib_idx]; 635 ib_chunk = &parser.chunks[parser.chunk_ib_idx];
641 parser.ib->length_dw = ib_chunk->length_dw; 636 parser.ib->length_dw = ib_chunk->length_dw;
642 memcpy((void *)parser.ib->ptr, ib_chunk->kdata, ib_chunk->length_dw*4);
643 *l = parser.ib->length_dw; 637 *l = parser.ib->length_dw;
644 r = r600_cs_parse(&parser); 638 r = r600_cs_parse(&parser);
645 if (r) { 639 if (r) {
@@ -647,6 +641,12 @@ int r600_cs_legacy(struct drm_device *dev, void *data, struct drm_file *filp,
647 r600_cs_parser_fini(&parser, r); 641 r600_cs_parser_fini(&parser, r);
648 return r; 642 return r;
649 } 643 }
644 r = radeon_cs_finish_pages(&parser);
645 if (r) {
646 DRM_ERROR("Invalid command stream !\n");
647 r600_cs_parser_fini(&parser, r);
648 return r;
649 }
650 r600_cs_parser_fini(&parser, r); 650 r600_cs_parser_fini(&parser, r);
651 return r; 651 return r;
652} 652}