diff options
author | Dave Airlie <airlied@redhat.com> | 2009-09-23 02:56:27 -0400 |
---|---|---|
committer | Dave Airlie <airlied@linux.ie> | 2009-09-24 23:08:18 -0400 |
commit | 513bcb4655e68706594e45dfa1d4b181500110ba (patch) | |
tree | ed457db4cfb202015866a131ad4e742503728fad /drivers/gpu/drm/radeon/r600_cs.c | |
parent | 35e4b7af21d77933abda3d41d1672589eb6c960c (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.c | 26 |
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 33b89cd8743e..c629b5aa4a3f 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, | |||
98 | static int r600_cs_packet_next_reloc_mm(struct radeon_cs_parser *p, | 98 | static 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, | |||
146 | static int r600_cs_packet_next_reloc_nomm(struct radeon_cs_parser *p, | 144 | static 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, | |||
218 | static int r600_packet3_check(struct radeon_cs_parser *p, | 214 | static 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 | } |