From 694125c6684f8bafbf5c4502659f1322fae33af2 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Sat, 10 Jul 2010 18:03:16 -0500 Subject: [PATCH 1/8] tiler: avoid lock-ups due to unmapped DMM entries Due to the address remapping done for 2d buffers, when a 2d buffer is allocated by userspace, it is possible that only partial pages map to valid physical pages of memory. But the MMU can only protect accesses to invalid addresses on the granualarity of full pages. Which results in the inconvenient situation where access to a perfectly valid address (from the point of view of a userspace process's memory map) can lock up the processor. To protect against this, a single dummy page is allocated at boot time and mapped in to the entire DMM space. When actual buffers are alloc'd, the mapping is replaced with the actual pages allocated for the buffer. And when the actual TILER buffer is freed, the mappings are set back to the dummy page. As a result, there is no longer the need for a clear() function in DMM. Instead the clear operation is simply remapping DMM entries back to the dummy page. As an added advantage, now pages are properly unmapped from DMM when TILER buffers are freed, avoiding the potential to corrupt pages that where previously allocated for TILER buffers. --- drivers/media/video/dmm/tmm.h | 12 ------------ drivers/media/video/dmm/tmm_pat.c | 1 - drivers/media/video/tiler/tiler.c | 27 ++++++++++++++++++++++++++- 3 files changed, 26 insertions(+), 14 deletions(-) diff --git a/drivers/media/video/dmm/tmm.h b/drivers/media/video/dmm/tmm.h index deaeca5..b86dbc3 100644 --- a/drivers/media/video/dmm/tmm.h +++ b/drivers/media/video/dmm/tmm.h @@ -27,7 +27,6 @@ struct tmm { u32 *(*get) (struct tmm *tmm, s32 num_pages); void (*free) (struct tmm *tmm, u32 *pages); s32 (*map) (struct tmm *tmm, struct pat_area area, u32 page_pa); - void (*clear) (struct tmm *tmm, struct pat_area area); void (*deinit) (struct tmm *tmm); }; @@ -68,17 +67,6 @@ s32 tmm_map(struct tmm *tmm, struct pat_area area, u32 page_pa) } /** - * Clears the physical address translator. - * @param area PAT area - */ -static inline -void tmm_clear(struct tmm *tmm, struct pat_area area) -{ - if (tmm && tmm->clear && tmm->pvt) - tmm->clear(tmm, area); -} - -/** * Checks whether tiler memory manager supports mapping */ static inline diff --git a/drivers/media/video/dmm/tmm_pat.c b/drivers/media/video/dmm/tmm_pat.c index 4ee59bd..c9c9aa5 100644 --- a/drivers/media/video/dmm/tmm_pat.c +++ b/drivers/media/video/dmm/tmm_pat.c @@ -316,7 +316,6 @@ struct tmm *tmm_pat_init(u32 pat_id) tmm->get = tmm_pat_get_pages; tmm->free = tmm_pat_free_pages; tmm->map = tmm_pat_map; - tmm->clear = NULL; /* not yet supported */ return tmm; } diff --git a/drivers/media/video/tiler/tiler.c b/drivers/media/video/tiler/tiler.c index 1c117eb..9ce065c 100644 --- a/drivers/media/video/tiler/tiler.c +++ b/drivers/media/video/tiler/tiler.c @@ -125,6 +125,9 @@ static struct tmm *tmm[TILER_FORMATS]; static u32 *dmac_va; static dma_addr_t dmac_pa; +static u32 *dummy_mem; +static u32 dummy_pa; + #define TCM(fmt) tcm[(fmt) - TILFMT_8BIT] #define TCM_SS(ssptr) TCM(TILER_GET_ACC_MODE(ssptr)) #define TCM_SET(fmt, i) tcm[(fmt) - TILFMT_8BIT] = i @@ -410,6 +413,7 @@ static void clear_pat(struct tmm *tmm, struct tcm_area *area) { struct pat_area p_area = {0}; struct tcm_area slice, area_s; + int i; tcm_for_each_slice(slice, *area, area_s) { p_area.x0 = slice.p0.x; @@ -417,7 +421,11 @@ static void clear_pat(struct tmm *tmm, struct tcm_area *area) p_area.x1 = slice.p1.x; p_area.y1 = slice.p1.y; - tmm_clear(tmm, p_area); + for (i = 0; inotifier); id = 0xda7a000; + /* Dummy page for filling unused entries in dmm (dmac_va): + */ + dummy_mem = alloc_pages_exact(PAGE_SIZE, GFP_KERNEL); + dummy_pa = virt_to_phys(dummy_mem); + + /* clear the entire dmm space: + */ + area.tcm = sita; + area.p0.x = 0; + area.p0.y = 0; + area.p1.x = TILER_WIDTH - 1; + area.p1.y = TILER_HEIGHT - 1; + clear_pat(tmm_pat, &area); + error: /* TODO: error handling for device registration */ if (r) { -- 1.6.6.1