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/radeon.h | |
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/radeon.h')
-rw-r--r-- | drivers/gpu/drm/radeon/radeon.h | 37 |
1 files changed, 36 insertions, 1 deletions
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index d5de53e06cec..7e34e4376f95 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h | |||
@@ -342,7 +342,7 @@ struct radeon_ib { | |||
342 | unsigned long idx; | 342 | unsigned long idx; |
343 | uint64_t gpu_addr; | 343 | uint64_t gpu_addr; |
344 | struct radeon_fence *fence; | 344 | struct radeon_fence *fence; |
345 | volatile uint32_t *ptr; | 345 | uint32_t *ptr; |
346 | uint32_t length_dw; | 346 | uint32_t length_dw; |
347 | }; | 347 | }; |
348 | 348 | ||
@@ -415,7 +415,12 @@ struct radeon_cs_reloc { | |||
415 | struct radeon_cs_chunk { | 415 | struct radeon_cs_chunk { |
416 | uint32_t chunk_id; | 416 | uint32_t chunk_id; |
417 | uint32_t length_dw; | 417 | uint32_t length_dw; |
418 | int kpage_idx[2]; | ||
419 | uint32_t *kpage[2]; | ||
418 | uint32_t *kdata; | 420 | uint32_t *kdata; |
421 | void __user *user_ptr; | ||
422 | int last_copied_page; | ||
423 | int last_page_index; | ||
419 | }; | 424 | }; |
420 | 425 | ||
421 | struct radeon_cs_parser { | 426 | struct radeon_cs_parser { |
@@ -438,8 +443,38 @@ struct radeon_cs_parser { | |||
438 | struct radeon_ib *ib; | 443 | struct radeon_ib *ib; |
439 | void *track; | 444 | void *track; |
440 | unsigned family; | 445 | unsigned family; |
446 | int parser_error; | ||
441 | }; | 447 | }; |
442 | 448 | ||
449 | extern int radeon_cs_update_pages(struct radeon_cs_parser *p, int pg_idx); | ||
450 | extern int radeon_cs_finish_pages(struct radeon_cs_parser *p); | ||
451 | |||
452 | |||
453 | static inline u32 radeon_get_ib_value(struct radeon_cs_parser *p, int idx) | ||
454 | { | ||
455 | struct radeon_cs_chunk *ibc = &p->chunks[p->chunk_ib_idx]; | ||
456 | u32 pg_idx, pg_offset; | ||
457 | u32 idx_value = 0; | ||
458 | int new_page; | ||
459 | |||
460 | pg_idx = (idx * 4) / PAGE_SIZE; | ||
461 | pg_offset = (idx * 4) % PAGE_SIZE; | ||
462 | |||
463 | if (ibc->kpage_idx[0] == pg_idx) | ||
464 | return ibc->kpage[0][pg_offset/4]; | ||
465 | if (ibc->kpage_idx[1] == pg_idx) | ||
466 | return ibc->kpage[1][pg_offset/4]; | ||
467 | |||
468 | new_page = radeon_cs_update_pages(p, pg_idx); | ||
469 | if (new_page < 0) { | ||
470 | p->parser_error = new_page; | ||
471 | return 0; | ||
472 | } | ||
473 | |||
474 | idx_value = ibc->kpage[new_page][pg_offset/4]; | ||
475 | return idx_value; | ||
476 | } | ||
477 | |||
443 | struct radeon_cs_packet { | 478 | struct radeon_cs_packet { |
444 | unsigned idx; | 479 | unsigned idx; |
445 | unsigned type; | 480 | unsigned type; |