Messages in this thread Patch in this message | | | From | Cort Dougan <> | Date | Sat, 16 Aug 2003 14:32:10 -0600 | Subject | [PATCH] PowerPC consistent_free() didn't free physical, just virtual (fixed) |
| |
consistent_free() was only freeing the virtual addresses before. This actually frees the virtual address and physical pages now. The hacked "track" array allows us to keep track of the address/order tuple so consistent_free() knows how large the area was without passing it in (and changing the arity of the function).
I discovered this by using consistent_alloc() and consistent_free() several times. Eventually, there was no RAM was left and instead of returning an error consistent_alloc() panics.
diff -Nru a/arch/ppc/mm/cachemap.c b/arch/ppc/mm/cachemap.c --- a/arch/ppc/mm/cachemap.c Sat Aug 16 14:31:27 2003 +++ b/arch/ppc/mm/cachemap.c Sat Aug 16 14:31:27 2003 @@ -60,6 +60,18 @@ * portions of the kernel with single large page TLB entries, and * still get unique uncached pages for consistent DMA. */ + +/* + * consistent_free() was only freeing the virtual addresses before. + * This actually frees the virtual address and physical pages now. + * The hacked "track" array allows us to keep track of the + * address/order tuple so consistent_free() knows how large the area + * was without passing it in (and changing the arity of the function). + * -- Cort <cort@fsmlabs.com> + */ +#define TRACK_SZ 100 +static unsigned long track[TRACK_SZ][3]; + void *consistent_alloc(int gfp, size_t size, dma_addr_t *dma_handle) { int order, err, i; @@ -125,6 +137,21 @@ return NULL; } + { + int i; + + for ( i = 0; i < TRACK_SZ ; i++ ) { + if ( track[i][0] == 0 ) { + break; + } + } + if ( i >= TRACK_SZ ) + panic("ran out of space\n"); + track[i][0] = ret; + track[i][1] = page; + track[i][2] = order; + } + return ret; } @@ -135,7 +162,26 @@ { if (in_interrupt()) BUG(); - vfree(vaddr); + + { + int i; + + for ( i = 0; i < TRACK_SZ ; i++ ) { + if ( track[i][0] == vaddr ) { + break; + } + } + if ( i >= TRACK_SZ ) + panic("couldn't find vaddr\n"); + + free_pages(track[i][1], track[i][2]); + + track[i][0] = 0; + track[i][1] = 0; + track[i][2] = 0; + + } + } /* - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| |