aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc
diff options
context:
space:
mode:
authorAlexei Shlychkov <x0177296@ti.com>2012-10-09 11:45:20 -0700
committerZiyann <jaraidaniel@gmail.com>2014-10-01 13:01:03 +0200
commit47fd5e746cf8e0e3205c03263a790e55835217d1 (patch)
treedcc04fec0c69fc5270f2a1b6c0b17db1c46c0829 /drivers/misc
parented95b60388a42bdef3b0293c60dc1e79d89faece (diff)
downloadkernel_samsung_tuna-47fd5e746cf8e0e3205c03263a790e55835217d1.zip
kernel_samsung_tuna-47fd5e746cf8e0e3205c03263a790e55835217d1.tar.gz
kernel_samsung_tuna-47fd5e746cf8e0e3205c03263a790e55835217d1.tar.bz2
gcx: improved MMU table dumping.
Change-Id: Ib08231c481533e349affd792ef944386dbcc0593 Signed-off-by: Alexei Shlychkov <x0177296@ti.com>
Diffstat (limited to 'drivers/misc')
-rw-r--r--drivers/misc/gcx/gccore/gcdbglog.c273
-rw-r--r--drivers/misc/gcx/gccore/gcmain.c2
-rw-r--r--drivers/misc/gcx/gccore/gcmmu.c12
-rw-r--r--drivers/misc/gcx/gccore/gcqueue.c3
4 files changed, 220 insertions, 70 deletions
diff --git a/drivers/misc/gcx/gccore/gcdbglog.c b/drivers/misc/gcx/gccore/gcdbglog.c
index 9d09e60..5113bc9 100644
--- a/drivers/misc/gcx/gccore/gcdbglog.c
+++ b/drivers/misc/gcx/gccore/gcdbglog.c
@@ -1586,103 +1586,233 @@ EXPORT_SYMBOL(gc_dump_phys_surface);
* MMU dumping functions.
*/
-typedef unsigned int (*pfn_get_present) (unsigned int entry);
-typedef void (*pfn_print_entry) (struct gcdbgfilter *filter, unsigned int zone,
- unsigned int index, unsigned int entry);
+struct gcmmuentry {
+ unsigned int entry;
+ bool exception;
+ bool present;
+
+ union {
+ struct gcmmumaster {
+ unsigned int slaveaddr;
+ unsigned int pagesize;
+ } mtlb;
+
+ struct gcmmuslave {
+ unsigned int pageaddr;
+ bool writable;
+ } stlb;
+ } u;
+};
+
+typedef void (*pfn_get_entry) (unsigned int entry,
+ struct gcmmuentry *gcmmuentry);
+typedef void (*pfn_print_entry) (struct gcdbgfilter *filter,
+ unsigned int zone,
+ unsigned int index,
+ struct gcmmuentry *gcmmuentry);
struct gcmmutable {
char *name;
+ bool master;
unsigned int entry_count;
unsigned int vacant_entry;
- pfn_get_present get_present;
+ pfn_get_entry get_entry;
pfn_print_entry print_entry;
};
-static unsigned int get_mtlb_present(unsigned int entry)
+static void get_mtlb_entry(unsigned int entry,
+ struct gcmmuentry *gcmmuentry)
{
- return entry & GCMMU_MTLB_PRESENT_MASK;
+ static const unsigned int pagesize[] = {
+ 1024 * 4,
+ 1024 * 64,
+ 1024 * 1024,
+ 1024 * 1024 * 16
+ };
+
+ gcmmuentry->entry = entry;
+ gcmmuentry->exception = ((entry & GCMMU_MTLB_EXCEPTION_MASK) != 0);
+ gcmmuentry->present = ((entry & GCMMU_MTLB_PRESENT_MASK) != 0);
+ gcmmuentry->u.mtlb.slaveaddr = entry & GCMMU_MTLB_SLAVE_MASK;
+ gcmmuentry->u.mtlb.pagesize =
+ pagesize[(entry & GCMMU_MTLB_PAGE_SIZE_MASK) >> 2];
}
-static unsigned int get_stlb_present(unsigned int entry)
+static void get_stlb_entry(unsigned int entry,
+ struct gcmmuentry *gcmmuentry)
{
- return entry & GCMMU_STLB_PRESENT_MASK;
+ gcmmuentry->entry = entry;
+ gcmmuentry->exception = ((entry & GCMMU_STLB_EXCEPTION_MASK) != 0);
+ gcmmuentry->present = ((entry & GCMMU_STLB_PRESENT_MASK) != 0);
+ gcmmuentry->u.stlb.pageaddr = entry & GCMMU_STLB_ADDRESS_MASK;
+ gcmmuentry->u.stlb.writable =
+ ((entry & GCMMU_STLB_WRITEABLE_MASK) != 0);
}
-static void print_mtlb_entry(struct gcdbgfilter *filter, unsigned int zone,
- unsigned int index, unsigned int entry)
+static void print_mtlb_entry(struct gcdbgfilter *filter,
+ unsigned int zone,
+ unsigned int index,
+ struct gcmmuentry *gcmmuentry)
{
gc_dump_string(filter, zone,
- " entry[%03d]: 0x%08X "
- "(stlb=0x%08X, ps=%d, ex=%d, pr=%d)\n",
- index, entry,
- entry & GCMMU_MTLB_SLAVE_MASK,
- (entry & GCMMU_MTLB_PAGE_SIZE_MASK) >> 2,
- (entry & GCMMU_MTLB_EXCEPTION_MASK) >> 1,
- (entry & GCMMU_MTLB_PRESENT_MASK)
- );
+ " entry[%04d]: 0x%08X "
+ "(stlbaddr=0x%08X, pagesize=%d, "
+ "exception=%d, present=%d)\n",
+ index, gcmmuentry->entry,
+ gcmmuentry->u.mtlb.slaveaddr,
+ gcmmuentry->u.mtlb.pagesize,
+ gcmmuentry->exception,
+ gcmmuentry->present);
}
-static void print_stlb_entry(struct gcdbgfilter *filter, unsigned int zone,
- unsigned int index, unsigned int entry)
+static void print_stlb_entry(struct gcdbgfilter *filter,
+ unsigned int zone,
+ unsigned int index,
+ struct gcmmuentry *gcmmuentry)
{
gc_dump_string(filter, zone,
- " entry[%03d]: 0x%08X "
- "(user=0x%08X, wr=%d, ex=%d, pr=%d)\n",
- index, entry,
- entry & GCMMU_STLB_ADDRESS_MASK,
- (entry & GCMMU_STLB_WRITEABLE_MASK) >> 2,
- (entry & GCMMU_STLB_EXCEPTION_MASK) >> 1,
- (entry & GCMMU_STLB_PRESENT_MASK)
- );
+ " entry[%04d]: 0x%08X "
+ "(pageaddr=0x%08X, writable=%d, "
+ "exception=%d, present=%d)\n",
+ index, gcmmuentry->entry,
+ gcmmuentry->u.stlb.pageaddr,
+ gcmmuentry->u.stlb.writable,
+ gcmmuentry->exception,
+ gcmmuentry->present);
+}
+
+static void finalize_vacant(struct gcdbgfilter *filter, unsigned int zone,
+ int index, int *vacant, int skipped)
+{
+ if (*vacant == -1)
+ return;
+
+ skipped = index - *vacant;
+ *vacant = -1;
+ gc_dump_string(filter, zone, "%15cskipped %d vacant entries\n",
+ ' ', skipped);
+}
+
+static void finalize_allocated(struct gcdbgfilter *filter, unsigned int zone,
+ int index, int *allocated, int skipped,
+ struct gcmmuentry *gcmmuentry,
+ unsigned int pagesize)
+{
+ unsigned int start, end;
+ int i;
+
+ if (*allocated == -1)
+ return;
+
+ skipped = index - *allocated;
+ *allocated = -1;
+ start = gcmmuentry->u.stlb.pageaddr - skipped * pagesize;
+ end = gcmmuentry->u.stlb.pageaddr + pagesize;
+
+ if (skipped > 5) {
+ gc_dump_string(filter, zone,
+ "%15cskipped %d allocated entries\n",
+ ' ', skipped);
+ gc_dump_string(filter, zone,
+ "%17callocated address range 0x%08X - 0x%08X\n",
+ ' ', start, end);
+ gc_dump_string(filter, zone,
+ "%17ctotal pages = %d\n",
+ ' ', skipped + 1);
+ gc_dump_string(filter, zone,
+ "%17ctotal buffer size = %d\n",
+ ' ', (skipped + 1) * pagesize);
+ } else {
+ gcmmuentry->u.stlb.pageaddr = start + pagesize;
+ gcmmuentry->entry = (start + pagesize)
+ & GCMMU_STLB_ADDRESS_MASK;
+
+ if (gcmmuentry->u.stlb.writable)
+ gcmmuentry->entry |= GCMMU_STLB_WRITEABLE_MASK;
+
+ if (gcmmuentry->exception)
+ gcmmuentry->entry |= GCMMU_STLB_EXCEPTION_MASK;
+
+ if (gcmmuentry->present)
+ gcmmuentry->entry |= GCMMU_STLB_PRESENT_MASK;
+
+ for (i = 0; i < skipped; i += 1) {
+ print_stlb_entry(filter, zone, index - skipped + i,
+ gcmmuentry);
+ gcmmuentry->u.stlb.pageaddr += pagesize;
+ }
+ }
}
static void dump_mmu_table(struct gcdbgfilter *filter, unsigned int zone,
- struct gcmmutable *desc, unsigned int physical,
- unsigned int *logical)
+ struct gcmmutable *desc, unsigned int physical,
+ unsigned int *logical, unsigned int pagesize)
{
- int present, vacant, skipped;
+ int vacant, allocated, skipped = 0;
+ bool sequential;
unsigned int entry, i;
+ struct gcmmuentry prev;
+ struct gcmmuentry curr;
gc_dump_string(filter, zone, "%s table:\n", desc->name);
gc_dump_string(filter, zone, " physical=0x%08X\n", physical);
vacant = -1;
+ allocated = -1;
+ curr.present = false;
+
for (i = 0; i < desc->entry_count; i += 1) {
entry = logical[i];
+ prev = curr;
+ desc->get_entry(entry, &curr);
+
+ if (!curr.present) {
+ finalize_allocated(filter, zone,
+ i, &allocated, skipped,
+ &prev, pagesize);
+
+ if (entry == desc->vacant_entry) {
+ if (vacant == -1)
+ vacant = i;
+ } else {
+ finalize_vacant(filter, zone,
+ i, &vacant, skipped);
+
+ gc_dump_string(filter, zone,
+ " entry[%03d]: "
+ "invalid entry (0x%08X)\n",
+ i, entry);
+ }
- present = desc->get_present(entry);
-
- if (!present && (entry == desc->vacant_entry)) {
- if (vacant == -1)
- vacant = i;
continue;
}
- if (vacant != -1) {
- skipped = i - vacant;
- vacant = -1;
- gc_dump_string(filter, zone,
- "%14cskipped %d vacant entries\n",
- skipped);
- }
+ finalize_vacant(filter, zone, i, &vacant, skipped);
- if (present) {
- desc->print_entry(filter, zone, i, entry);
- } else {
- gc_dump_string(filter, zone,
- " entry[%03d]: "
- "invalid entry value (0x%08X)\n",
- i, entry);
+ sequential
+ = (!desc->master
+ && (curr.present == prev.present)
+ && (curr.exception == prev.exception)
+ && (curr.u.stlb.writable == prev.u.stlb.writable)
+ && (curr.u.stlb.pageaddr == prev.u.stlb.pageaddr
+ + pagesize));
+
+ if (sequential) {
+ if (allocated == -1)
+ allocated = i;
+
+ continue;
}
- }
- if (vacant != -1) {
- skipped = i - vacant;
- vacant = -1;
- gc_dump_string(filter, zone,
- "%14cskipped %d vacant entries\n",
- skipped);
+ finalize_allocated(filter, zone, i, &allocated, skipped,
+ &prev, pagesize);
+
+ desc->print_entry(filter, zone, i, &curr);
}
+
+ finalize_vacant(filter, zone, i, &vacant, skipped);
+ finalize_allocated(filter, zone, i, &allocated, skipped,
+ &prev, pagesize);
}
void gc_dump_mmu(struct gcdbgfilter *filter, unsigned int zone,
@@ -1690,36 +1820,45 @@ void gc_dump_mmu(struct gcdbgfilter *filter, unsigned int zone,
{
static struct gcmmutable mtlb_desc = {
"Master",
+ true,
GCMMU_MTLB_ENTRY_NUM,
GCMMU_MTLB_ENTRY_VACANT,
- get_mtlb_present,
+ get_mtlb_entry,
print_mtlb_entry
};
static struct gcmmutable stlb_desc = {
"Slave",
+ false,
GCMMU_STLB_ENTRY_NUM,
GCMMU_STLB_ENTRY_VACANT,
- get_stlb_present,
+ get_stlb_entry,
print_stlb_entry
};
unsigned int i;
+ struct gcmmuentry master;
GCDUMPARENAS(zone, "vacant arenas", &gcmmucontext->vacant);
GCDUMPARENAS(zone, "allocated arenas", &gcmmucontext->allocated);
gc_dump_string(filter, zone,
- "*** MMU DUMP ***\n");
+ "*** MMU DUMP ***\n");
- dump_mmu_table(filter, zone, &mtlb_desc, gcmmucontext->master.physical,
- gcmmucontext->master.logical);
+ dump_mmu_table(filter, zone, &mtlb_desc,
+ gcmmucontext->master.physical,
+ gcmmucontext->master.logical, 0);
- for (i = 0; i < GCMMU_MTLB_ENTRY_NUM; i += 1)
- if (gcmmucontext->slave[i].logical != NULL)
- dump_mmu_table(filter, zone, &stlb_desc,
- gcmmucontext->slave[i].physical,
- gcmmucontext->slave[i].logical);
+ for (i = 0; i < GCMMU_MTLB_ENTRY_NUM; i += 1) {
+ if (gcmmucontext->slave[i].logical == NULL)
+ continue;
+
+ get_mtlb_entry(gcmmucontext->master.logical[i], &master);
+ dump_mmu_table(filter, zone, &stlb_desc,
+ gcmmucontext->slave[i].physical,
+ gcmmucontext->slave[i].logical,
+ master.u.mtlb.pagesize);
+ }
}
EXPORT_SYMBOL(gc_dump_mmu);
diff --git a/drivers/misc/gcx/gccore/gcmain.c b/drivers/misc/gcx/gccore/gcmain.c
index 91ec560..550924d 100644
--- a/drivers/misc/gcx/gccore/gcmain.c
+++ b/drivers/misc/gcx/gccore/gcmain.c
@@ -644,7 +644,7 @@ void gc_commit(struct gcicommit *gcicommit, bool fromuser)
/* Execute the buffer. */
gcicommit->gcerror = gcqueue_execute(gccorecontext, false,
- gcicommit->asynchronous);
+ gcicommit->asynchronous);
exit:
GCUNLOCK(&gccorecontext->mmucontextlock);
diff --git a/drivers/misc/gcx/gccore/gcmmu.c b/drivers/misc/gcx/gccore/gcmmu.c
index f1df611..42e68e4 100644
--- a/drivers/misc/gcx/gccore/gcmmu.c
+++ b/drivers/misc/gcx/gccore/gcmmu.c
@@ -30,6 +30,8 @@
#define GCZONE_FIXUP (1 << 4)
#define GCZONE_FLUSH (1 << 5)
#define GCZONE_ARENA (1 << 6)
+#define GCZONE_DUMPMAP (1 << 7)
+#define GCZONE_DUMPUNMAP (1 << 8)
GCDBG_FILTERDEF(mmu, GCZONE_NONE,
"init",
@@ -38,7 +40,9 @@ GCDBG_FILTERDEF(mmu, GCZONE_NONE,
"master",
"fixup",
"flush",
- "arena")
+ "arena",
+ "dumpmap",
+ "dumpunmap")
/*******************************************************************************
@@ -936,6 +940,9 @@ enum gcerror gcmmu_map(struct gccorecontext *gccorecontext,
GCDBG(GCZONE_MAPPING, "mapped %d bytes at 0x%08X\n",
vacant->size, vacant->address);
+ /* Dump tables. */
+ GCDUMPMMU(GCZONE_DUMPMAP, gcmmucontext);
+
exit:
if (parray_alloc != NULL) {
kfree(parray_alloc);
@@ -1123,6 +1130,9 @@ enum gcerror gcmmu_unmap(struct gccorecontext *gccorecontext,
/* Invalidate the MMU. */
gcmmucontext->dirty = true;
+ /* Dump tables. */
+ GCDUMPMMU(GCZONE_DUMPUNMAP, gcmmucontext);
+
exit:
if (locked)
GCUNLOCK(&gcmmucontext->lock);
diff --git a/drivers/misc/gcx/gccore/gcqueue.c b/drivers/misc/gcx/gccore/gcqueue.c
index a7a1af9..c5a1921 100644
--- a/drivers/misc/gcx/gccore/gcqueue.c
+++ b/drivers/misc/gcx/gccore/gcqueue.c
@@ -696,6 +696,7 @@ static int gccmdthread(void *_gccorecontext)
/* MMU error? */
if (try_wait_for_completion(&gcqueue->mmuerror)) {
static char *mmuerror[] = {
+ " no error",
" slave not present",
" page not present",
" write violation"
@@ -718,7 +719,7 @@ static int gccmdthread(void *_gccorecontext)
GCERR("MMU%d is at fault:\n", i);
if (mmucode >= countof(mmuerror))
- GCERR(" unknown state.\n", mmucode);
+ GCERR(" unknown state %d.\n", mmucode);
else
GCERR("%s.\n", mmuerror[mmucode]);