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
parent
881ee70ab7
commit
37fb2ac407
|
@ -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,
|
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 =
|
struct drm_agp_ttm_backend *agp_be =
|
||||||
container_of(backend, struct drm_agp_ttm_backend, backend);
|
container_of(backend, struct drm_agp_ttm_backend, backend);
|
||||||
struct page **cur_page, **last_page = pages + num_pages;
|
struct page **cur_page, **last_page = pages + num_pages;
|
||||||
DRM_AGP_MEM *mem;
|
DRM_AGP_MEM *mem;
|
||||||
|
int dummy_page_count = 0;
|
||||||
|
|
||||||
if (drm_alloc_memctl(num_pages * sizeof(void *)))
|
if (drm_alloc_memctl(num_pages * sizeof(void *)))
|
||||||
return -1;
|
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);
|
DRM_DEBUG("Current page count is %ld\n", (long) mem->page_count);
|
||||||
mem->page_count = 0;
|
mem->page_count = 0;
|
||||||
for (cur_page = pages; cur_page < last_page; ++cur_page)
|
for (cur_page = pages; cur_page < last_page; ++cur_page) {
|
||||||
mem->memory[mem->page_count++] = phys_to_gart(page_to_phys(*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;
|
agp_be->mem = mem;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -263,7 +263,8 @@ struct drm_ttm_backend;
|
||||||
struct drm_ttm_backend_func {
|
struct drm_ttm_backend_func {
|
||||||
int (*needs_ub_cache_adjust) (struct drm_ttm_backend *backend);
|
int (*needs_ub_cache_adjust) (struct drm_ttm_backend *backend);
|
||||||
int (*populate) (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);
|
void (*clear) (struct drm_ttm_backend *backend);
|
||||||
int (*bind) (struct drm_ttm_backend *backend,
|
int (*bind) (struct drm_ttm_backend *backend,
|
||||||
struct drm_bo_mem_reg *bo_mem);
|
struct drm_bo_mem_reg *bo_mem);
|
||||||
|
|
|
@ -262,7 +262,6 @@ int drm_ttm_set_user(struct drm_ttm *ttm,
|
||||||
{
|
{
|
||||||
struct mm_struct *mm = tsk->mm;
|
struct mm_struct *mm = tsk->mm;
|
||||||
int ret;
|
int ret;
|
||||||
int i;
|
|
||||||
int write = (ttm->page_flags & DRM_TTM_PAGE_WRITE) != 0;
|
int write = (ttm->page_flags & DRM_TTM_PAGE_WRITE) != 0;
|
||||||
|
|
||||||
BUG_ON(num_pages != ttm->num_pages);
|
BUG_ON(num_pages != ttm->num_pages);
|
||||||
|
@ -278,11 +277,6 @@ int drm_ttm_set_user(struct drm_ttm *ttm,
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < num_pages; ++i) {
|
|
||||||
if (ttm->pages[i] == NULL)
|
|
||||||
ttm->pages[i] = ttm->dummy_read_page;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -304,12 +298,14 @@ int drm_ttm_populate(struct drm_ttm *ttm)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
be = ttm->be;
|
be = ttm->be;
|
||||||
|
if (ttm->page_flags & DRM_TTM_PAGE_WRITE) {
|
||||||
for (i = 0; i < ttm->num_pages; ++i) {
|
for (i = 0; i < ttm->num_pages; ++i) {
|
||||||
page = drm_ttm_get_page(ttm, i);
|
page = drm_ttm_get_page(ttm, i);
|
||||||
if (!page)
|
if (!page)
|
||||||
return -ENOMEM;
|
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;
|
ttm->state = ttm_unbound;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ nouveau_sgdma_needs_ub_cache_adjust(struct drm_ttm_backend *be)
|
||||||
|
|
||||||
static int
|
static int
|
||||||
nouveau_sgdma_populate(struct drm_ttm_backend *be, unsigned long num_pages,
|
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;
|
struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
|
||||||
int p, d, o;
|
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;
|
nvbe->pages_populated = d = 0;
|
||||||
for (p = 0; p < num_pages; p++) {
|
for (p = 0; p < num_pages; p++) {
|
||||||
for (o = 0; o < PAGE_SIZE; o += NV_CTXDMA_PAGE_SIZE) {
|
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,
|
nvbe->pagelist[d] = pci_map_page(nvbe->dev->pdev,
|
||||||
pages[p], o,
|
page, o,
|
||||||
NV_CTXDMA_PAGE_SIZE,
|
NV_CTXDMA_PAGE_SIZE,
|
||||||
PCI_DMA_BIDIRECTIONAL);
|
PCI_DMA_BIDIRECTIONAL);
|
||||||
if (pci_dma_mapping_error(nvbe->pagelist[d])) {
|
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;
|
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);
|
DRM_ERROR("failed populate: %d\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue