aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2012-04-03 11:23:41 -0400
committerDave Airlie <airlied@redhat.com>2012-04-12 04:42:54 -0400
commit6a7068b4ef17dfb9de3191321f1adc91fa1659ca (patch)
tree555cc6a57df84d95a24faafd796868101ee1943a /drivers
parent2099810f903caa1920f3ef6014fb7f36e4786490 (diff)
drm/radeon/kms: attempt to avoid copying data twice on coherent cards. (v3)
On coherent systems (not-AGP) the IB should be in cached memory so should be just as fast, so we can avoid copying to temporary pages and just use it directly. provides minor speedups on rv530: gears ~1820->1860, ipers: 29.9->30.6, but always good to use less CPU if we can. v3: cleanup unneeded bits. Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/radeon/radeon_cs.c37
1 files changed, 24 insertions, 13 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c
index 5cac83278338..e7b0b5d51bc3 100644
--- a/drivers/gpu/drm/radeon/radeon_cs.c
+++ b/drivers/gpu/drm/radeon/radeon_cs.c
@@ -278,11 +278,16 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data)
278 p->chunks[p->chunk_ib_idx].length_dw); 278 p->chunks[p->chunk_ib_idx].length_dw);
279 return -EINVAL; 279 return -EINVAL;
280 } 280 }
281 p->chunks[p->chunk_ib_idx].kpage[0] = kmalloc(PAGE_SIZE, GFP_KERNEL); 281 if ((p->rdev->flags & RADEON_IS_AGP)) {
282 p->chunks[p->chunk_ib_idx].kpage[1] = kmalloc(PAGE_SIZE, GFP_KERNEL); 282 p->chunks[p->chunk_ib_idx].kpage[0] = kmalloc(PAGE_SIZE, GFP_KERNEL);
283 if (p->chunks[p->chunk_ib_idx].kpage[0] == NULL || 283 p->chunks[p->chunk_ib_idx].kpage[1] = kmalloc(PAGE_SIZE, GFP_KERNEL);
284 p->chunks[p->chunk_ib_idx].kpage[1] == NULL) 284 if (p->chunks[p->chunk_ib_idx].kpage[0] == NULL ||
285 return -ENOMEM; 285 p->chunks[p->chunk_ib_idx].kpage[1] == NULL) {
286 kfree(p->chunks[i].kpage[0]);
287 kfree(p->chunks[i].kpage[1]);
288 return -ENOMEM;
289 }
290 }
286 p->chunks[p->chunk_ib_idx].kpage_idx[0] = -1; 291 p->chunks[p->chunk_ib_idx].kpage_idx[0] = -1;
287 p->chunks[p->chunk_ib_idx].kpage_idx[1] = -1; 292 p->chunks[p->chunk_ib_idx].kpage_idx[1] = -1;
288 p->chunks[p->chunk_ib_idx].last_copied_page = -1; 293 p->chunks[p->chunk_ib_idx].last_copied_page = -1;
@@ -323,8 +328,10 @@ static void radeon_cs_parser_fini(struct radeon_cs_parser *parser, int error)
323 kfree(parser->relocs_ptr); 328 kfree(parser->relocs_ptr);
324 for (i = 0; i < parser->nchunks; i++) { 329 for (i = 0; i < parser->nchunks; i++) {
325 kfree(parser->chunks[i].kdata); 330 kfree(parser->chunks[i].kdata);
326 kfree(parser->chunks[i].kpage[0]); 331 if ((parser->rdev->flags & RADEON_IS_AGP)) {
327 kfree(parser->chunks[i].kpage[1]); 332 kfree(parser->chunks[i].kpage[0]);
333 kfree(parser->chunks[i].kpage[1]);
334 }
328 } 335 }
329 kfree(parser->chunks); 336 kfree(parser->chunks);
330 kfree(parser->chunks_array); 337 kfree(parser->chunks_array);
@@ -573,6 +580,7 @@ int radeon_cs_update_pages(struct radeon_cs_parser *p, int pg_idx)
573 struct radeon_cs_chunk *ibc = &p->chunks[p->chunk_ib_idx]; 580 struct radeon_cs_chunk *ibc = &p->chunks[p->chunk_ib_idx];
574 int i; 581 int i;
575 int size = PAGE_SIZE; 582 int size = PAGE_SIZE;
583 bool copy1 = (p->rdev->flags & RADEON_IS_AGP) ? false : true;
576 584
577 for (i = ibc->last_copied_page + 1; i < pg_idx; i++) { 585 for (i = ibc->last_copied_page + 1; i < pg_idx; i++) {
578 if (DRM_COPY_FROM_USER(p->ib->ptr + (i * (PAGE_SIZE/4)), 586 if (DRM_COPY_FROM_USER(p->ib->ptr + (i * (PAGE_SIZE/4)),
@@ -583,14 +591,16 @@ int radeon_cs_update_pages(struct radeon_cs_parser *p, int pg_idx)
583 } 591 }
584 } 592 }
585 593
586 new_page = ibc->kpage_idx[0] < ibc->kpage_idx[1] ? 0 : 1;
587
588 if (pg_idx == ibc->last_page_index) { 594 if (pg_idx == ibc->last_page_index) {
589 size = (ibc->length_dw * 4) % PAGE_SIZE; 595 size = (ibc->length_dw * 4) % PAGE_SIZE;
590 if (size == 0) 596 if (size == 0)
591 size = PAGE_SIZE; 597 size = PAGE_SIZE;
592 } 598 }
593 599
600 new_page = ibc->kpage_idx[0] < ibc->kpage_idx[1] ? 0 : 1;
601 if (copy1)
602 ibc->kpage[new_page] = p->ib->ptr + (pg_idx * (PAGE_SIZE / 4));
603
594 if (DRM_COPY_FROM_USER(ibc->kpage[new_page], 604 if (DRM_COPY_FROM_USER(ibc->kpage[new_page],
595 ibc->user_ptr + (pg_idx * PAGE_SIZE), 605 ibc->user_ptr + (pg_idx * PAGE_SIZE),
596 size)) { 606 size)) {
@@ -598,8 +608,9 @@ int radeon_cs_update_pages(struct radeon_cs_parser *p, int pg_idx)
598 return 0; 608 return 0;
599 } 609 }
600 610
601 /* copy to IB here */ 611 /* copy to IB for non single case */
602 memcpy((void *)(p->ib->ptr+(pg_idx*(PAGE_SIZE/4))), ibc->kpage[new_page], size); 612 if (!copy1)
613 memcpy((void *)(p->ib->ptr+(pg_idx*(PAGE_SIZE/4))), ibc->kpage[new_page], size);
603 614
604 ibc->last_copied_page = pg_idx; 615 ibc->last_copied_page = pg_idx;
605 ibc->kpage_idx[new_page] = pg_idx; 616 ibc->kpage_idx[new_page] = pg_idx;