Use dummy_read_page for unpopulated kernel-allocated ttm pages.

Previously, dummy_read_page was used only for read-only user allocations; it
filled in pages that were not present in the user address map (presumably,
these were allocated but never written to pages).

This patch allows them to be used for read-only ttms allocated from the
kernel, so that applications can over-allocate buffers without forcing every
page to be allocated.
main
Keith Packard 2007-12-16 01:47:51 -08:00
parent 881ee70ab7
commit 37fb2ac407
4 changed files with 28 additions and 18 deletions

View File

@ -505,12 +505,14 @@ static int drm_agp_needs_unbind_cache_adjust(struct drm_ttm_backend *backend)
static int drm_agp_populate(struct drm_ttm_backend *backend,
unsigned long num_pages, struct page **pages)
unsigned long num_pages, struct page **pages,
struct page *dummy_read_page)
{
struct drm_agp_ttm_backend *agp_be =
container_of(backend, struct drm_agp_ttm_backend, backend);
struct page **cur_page, **last_page = pages + num_pages;
DRM_AGP_MEM *mem;
int dummy_page_count = 0;
if (drm_alloc_memctl(num_pages * sizeof(void *)))
return -1;
@ -528,8 +530,16 @@ static int drm_agp_populate(struct drm_ttm_backend *backend,
DRM_DEBUG("Current page count is %ld\n", (long) mem->page_count);
mem->page_count = 0;
for (cur_page = pages; cur_page < last_page; ++cur_page)
mem->memory[mem->page_count++] = phys_to_gart(page_to_phys(*cur_page));
for (cur_page = pages; cur_page < last_page; ++cur_page) {
struct page *page = *cur_page;
if (!page) {
page = dummy_read_page;
++dummy_page_count;
}
mem->memory[mem->page_count++] = phys_to_gart(page_to_phys(page));
}
if (dummy_page_count)
DRM_DEBUG("Mapped %d dummy pages\n", dummy_page_count);
agp_be->mem = mem;
return 0;
}

View File

@ -263,7 +263,8 @@ struct drm_ttm_backend;
struct drm_ttm_backend_func {
int (*needs_ub_cache_adjust) (struct drm_ttm_backend *backend);
int (*populate) (struct drm_ttm_backend *backend,
unsigned long num_pages, struct page **pages);
unsigned long num_pages, struct page **pages,
struct page *dummy_read_page);
void (*clear) (struct drm_ttm_backend *backend);
int (*bind) (struct drm_ttm_backend *backend,
struct drm_bo_mem_reg *bo_mem);

View File

@ -262,7 +262,6 @@ int drm_ttm_set_user(struct drm_ttm *ttm,
{
struct mm_struct *mm = tsk->mm;
int ret;
int i;
int write = (ttm->page_flags & DRM_TTM_PAGE_WRITE) != 0;
BUG_ON(num_pages != ttm->num_pages);
@ -278,11 +277,6 @@ int drm_ttm_set_user(struct drm_ttm *ttm,
return -ENOMEM;
}
for (i = 0; i < num_pages; ++i) {
if (ttm->pages[i] == NULL)
ttm->pages[i] = ttm->dummy_read_page;
}
return 0;
}
@ -304,12 +298,14 @@ int drm_ttm_populate(struct drm_ttm *ttm)
return 0;
be = ttm->be;
if (ttm->page_flags & DRM_TTM_PAGE_WRITE) {
for (i = 0; i < ttm->num_pages; ++i) {
page = drm_ttm_get_page(ttm, i);
if (!page)
return -ENOMEM;
}
be->func->populate(be, ttm->num_pages, ttm->pages);
}
be->func->populate(be, ttm->num_pages, ttm->pages, ttm->dummy_read_page);
ttm->state = ttm_unbound;
return 0;
}

View File

@ -25,7 +25,7 @@ nouveau_sgdma_needs_ub_cache_adjust(struct drm_ttm_backend *be)
static int
nouveau_sgdma_populate(struct drm_ttm_backend *be, unsigned long num_pages,
struct page **pages)
struct page **pages, struct page *dummy_read_page)
{
struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
int p, d, o;
@ -41,8 +41,11 @@ nouveau_sgdma_populate(struct drm_ttm_backend *be, unsigned long num_pages,
nvbe->pages_populated = d = 0;
for (p = 0; p < num_pages; p++) {
for (o = 0; o < PAGE_SIZE; o += NV_CTXDMA_PAGE_SIZE) {
struct page *page = pages[p];
if (!page)
page = dummy_read_page;
nvbe->pagelist[d] = pci_map_page(nvbe->dev->pdev,
pages[p], o,
page, o,
NV_CTXDMA_PAGE_SIZE,
PCI_DMA_BIDIRECTIONAL);
if (pci_dma_mapping_error(nvbe->pagelist[d])) {
@ -299,7 +302,7 @@ nouveau_sgdma_nottm_hack_init(struct drm_device *dev)
}
dev_priv->gart_info.sg_handle = sgreq.handle;
if ((ret = be->func->populate(be, dev->sg->pages, dev->sg->pagelist))) {
if ((ret = be->func->populate(be, dev->sg->pages, dev->sg->pagelist, dev->bm.dummy_read_page))) {
DRM_ERROR("failed populate: %d\n", ret);
return ret;
}