2019-05-29 07:17:56 -07:00
// SPDX-License-Identifier: GPL-2.0-only
2013-03-22 16:34:04 +02:00
/*
* Copyright ( C ) 2010 Google , Inc .
* Author : Erik Gilling < konkers @ android . com >
*
* Copyright ( C ) 2011 - 2013 NVIDIA Corporation
*/
2013-10-09 10:32:54 +02:00
# include "../dev.h"
# include "../debug.h"
# include "../cdma.h"
# include "../channel.h"
2013-03-22 16:34:04 +02:00
# define HOST1X_DEBUG_MAX_PAGE_OFFSET 102400
enum {
HOST1X_OPCODE_SETCLASS = 0x00 ,
HOST1X_OPCODE_INCR = 0x01 ,
HOST1X_OPCODE_NONINCR = 0x02 ,
HOST1X_OPCODE_MASK = 0x03 ,
HOST1X_OPCODE_IMM = 0x04 ,
HOST1X_OPCODE_RESTART = 0x05 ,
HOST1X_OPCODE_GATHER = 0x06 ,
2017-09-28 15:50:42 +03:00
HOST1X_OPCODE_SETSTRMID = 0x07 ,
HOST1X_OPCODE_SETAPPID = 0x08 ,
HOST1X_OPCODE_SETPYLD = 0x09 ,
HOST1X_OPCODE_INCR_W = 0x0a ,
HOST1X_OPCODE_NONINCR_W = 0x0b ,
HOST1X_OPCODE_GATHER_W = 0x0c ,
HOST1X_OPCODE_RESTART_W = 0x0d ,
2013-03-22 16:34:04 +02:00
HOST1X_OPCODE_EXTEND = 0x0e ,
} ;
enum {
HOST1X_OPCODE_EXTEND_ACQUIRE_MLOCK = 0x00 ,
HOST1X_OPCODE_EXTEND_RELEASE_MLOCK = 0x01 ,
} ;
2017-09-28 15:50:42 +03:00
# define INVALID_PAYLOAD 0xffffffff
static unsigned int show_channel_command ( struct output * o , u32 val ,
u32 * payload )
2013-03-22 16:34:04 +02:00
{
2017-09-28 15:50:42 +03:00
unsigned int mask , subop , num , opcode ;
opcode = val > > 28 ;
2013-03-22 16:34:04 +02:00
2017-09-28 15:50:42 +03:00
switch ( opcode ) {
2013-03-22 16:34:04 +02:00
case HOST1X_OPCODE_SETCLASS :
mask = val & 0x3f ;
if ( mask ) {
2017-09-28 15:50:41 +03:00
host1x_debug_cont ( o , " SETCL(class=%03x, offset=%03x, mask=%02x, [ " ,
2013-03-22 16:34:04 +02:00
val > > 6 & 0x3ff ,
val > > 16 & 0xfff , mask ) ;
return hweight8 ( mask ) ;
}
2017-09-28 15:50:41 +03:00
host1x_debug_cont ( o , " SETCL(class=%03x) \n " , val > > 6 & 0x3ff ) ;
2016-06-23 11:33:31 +02:00
return 0 ;
2013-03-22 16:34:04 +02:00
case HOST1X_OPCODE_INCR :
2017-09-28 15:50:41 +03:00
num = val & 0xffff ;
host1x_debug_cont ( o , " INCR(offset=%03x, [ " ,
2013-03-22 16:34:04 +02:00
val > > 16 & 0xfff ) ;
2017-09-28 15:50:41 +03:00
if ( ! num )
host1x_debug_cont ( o , " ]) \n " ) ;
return num ;
2013-03-22 16:34:04 +02:00
case HOST1X_OPCODE_NONINCR :
2017-09-28 15:50:41 +03:00
num = val & 0xffff ;
host1x_debug_cont ( o , " NONINCR(offset=%03x, [ " ,
2013-03-22 16:34:04 +02:00
val > > 16 & 0xfff ) ;
2017-09-28 15:50:41 +03:00
if ( ! num )
host1x_debug_cont ( o , " ]) \n " ) ;
return num ;
2013-03-22 16:34:04 +02:00
case HOST1X_OPCODE_MASK :
mask = val & 0xffff ;
2017-09-28 15:50:41 +03:00
host1x_debug_cont ( o , " MASK(offset=%03x, mask=%03x, [ " ,
2013-03-22 16:34:04 +02:00
val > > 16 & 0xfff , mask ) ;
2017-09-28 15:50:41 +03:00
if ( ! mask )
host1x_debug_cont ( o , " ]) \n " ) ;
2013-03-22 16:34:04 +02:00
return hweight16 ( mask ) ;
case HOST1X_OPCODE_IMM :
2017-09-28 15:50:41 +03:00
host1x_debug_cont ( o , " IMM(offset=%03x, data=%03x) \n " ,
2013-03-22 16:34:04 +02:00
val > > 16 & 0xfff , val & 0xffff ) ;
return 0 ;
case HOST1X_OPCODE_RESTART :
2017-09-28 15:50:41 +03:00
host1x_debug_cont ( o , " RESTART(offset=%08x) \n " , val < < 4 ) ;
2013-03-22 16:34:04 +02:00
return 0 ;
case HOST1X_OPCODE_GATHER :
2017-09-28 15:50:41 +03:00
host1x_debug_cont ( o , " GATHER(offset=%03x, insert=%d, type=%d, count=%04x, addr=[ " ,
2013-03-22 16:34:04 +02:00
val > > 16 & 0xfff , val > > 15 & 0x1 ,
val > > 14 & 0x1 , val & 0x3fff ) ;
return 1 ;
2017-09-28 15:50:42 +03:00
# if HOST1X_HW >= 6
case HOST1X_OPCODE_SETSTRMID :
host1x_debug_cont ( o , " SETSTRMID(offset=%06x) \n " ,
val & 0x3fffff ) ;
return 0 ;
case HOST1X_OPCODE_SETAPPID :
host1x_debug_cont ( o , " SETAPPID(appid=%02x) \n " , val & 0xff ) ;
return 0 ;
case HOST1X_OPCODE_SETPYLD :
* payload = val & 0xffff ;
host1x_debug_cont ( o , " SETPYLD(data=%04x) \n " , * payload ) ;
return 0 ;
case HOST1X_OPCODE_INCR_W :
case HOST1X_OPCODE_NONINCR_W :
host1x_debug_cont ( o , " %s(offset=%06x, " ,
opcode = = HOST1X_OPCODE_INCR_W ?
" INCR_W " : " NONINCR_W " ,
val & 0x3fffff ) ;
if ( * payload = = 0 ) {
host1x_debug_cont ( o , " []) \n " ) ;
return 0 ;
} else if ( * payload = = INVALID_PAYLOAD ) {
host1x_debug_cont ( o , " unknown) \n " ) ;
return 0 ;
} else {
host1x_debug_cont ( o , " [ " ) ;
return * payload ;
}
case HOST1X_OPCODE_GATHER_W :
host1x_debug_cont ( o , " GATHER_W(count=%04x, addr=[ " ,
val & 0x3fff ) ;
return 2 ;
# endif
2013-03-22 16:34:04 +02:00
case HOST1X_OPCODE_EXTEND :
subop = val > > 24 & 0xf ;
if ( subop = = HOST1X_OPCODE_EXTEND_ACQUIRE_MLOCK )
2017-09-28 15:50:41 +03:00
host1x_debug_cont ( o , " ACQUIRE_MLOCK(index=%d) \n " ,
2013-03-22 16:34:04 +02:00
val & 0xff ) ;
else if ( subop = = HOST1X_OPCODE_EXTEND_RELEASE_MLOCK )
2017-09-28 15:50:41 +03:00
host1x_debug_cont ( o , " RELEASE_MLOCK(index=%d) \n " ,
2013-03-22 16:34:04 +02:00
val & 0xff ) ;
else
2017-09-28 15:50:41 +03:00
host1x_debug_cont ( o , " EXTEND_UNKNOWN(%08x) \n " , val ) ;
2013-03-22 16:34:04 +02:00
return 0 ;
default :
2017-09-28 15:50:41 +03:00
host1x_debug_cont ( o , " UNKNOWN \n " ) ;
2013-03-22 16:34:04 +02:00
return 0 ;
}
}
static void show_gather ( struct output * o , phys_addr_t phys_addr ,
unsigned int words , struct host1x_cdma * cdma ,
phys_addr_t pin_addr , u32 * map_addr )
{
/* Map dmaget cursor to corresponding mem handle */
u32 offset = phys_addr - pin_addr ;
unsigned int data_count = 0 , i ;
2017-09-28 15:50:42 +03:00
u32 payload = INVALID_PAYLOAD ;
2013-03-22 16:34:04 +02:00
/*
* Sometimes we ' re given different hardware address to the same
* page - in these cases the offset will get an invalid number and
* we just have to bail out .
*/
if ( offset > HOST1X_DEBUG_MAX_PAGE_OFFSET ) {
host1x_debug_output ( o , " [address mismatch] \n " ) ;
return ;
}
for ( i = 0 ; i < words ; i + + ) {
u32 addr = phys_addr + i * 4 ;
u32 val = * ( map_addr + offset / 4 + i ) ;
if ( ! data_count ) {
2017-09-28 15:50:41 +03:00
host1x_debug_output ( o , " %08x: %08x: " , addr , val ) ;
2017-09-28 15:50:42 +03:00
data_count = show_channel_command ( o , val , & payload ) ;
2013-03-22 16:34:04 +02:00
} else {
2017-09-28 15:50:41 +03:00
host1x_debug_cont ( o , " %08x%s " , val ,
data_count > 1 ? " , " : " ]) \n " ) ;
2013-03-22 16:34:04 +02:00
data_count - - ;
}
}
}
static void show_channel_gathers ( struct output * o , struct host1x_cdma * cdma )
{
2020-06-29 06:18:42 +03:00
struct push_buffer * pb = & cdma - > push_buffer ;
2013-03-22 16:34:04 +02:00
struct host1x_job * job ;
2020-06-29 06:18:42 +03:00
host1x_debug_output ( o , " PUSHBUF at %pad, %u words \n " ,
& pb - > dma , pb - > size / 4 ) ;
show_gather ( o , pb - > dma , pb - > size / 4 , cdma , pb - > dma , pb - > mapped ) ;
2013-03-22 16:34:04 +02:00
list_for_each_entry ( job , & cdma - > sync_queue , list ) {
2016-06-22 16:44:07 +02:00
unsigned int i ;
2013-03-22 16:34:04 +02:00
host1x_debug_output ( o , " \n %p: JOB, syncpt_id=%d, syncpt_val=%d, first_get=%08x, timeout=%d num_slots=%d, num_handles=%d \n " ,
job , job - > syncpt_id , job - > syncpt_end ,
job - > first_get , job - > timeout ,
job - > num_slots , job - > num_unpins ) ;
for ( i = 0 ; i < job - > num_gathers ; i + + ) {
struct host1x_job_gather * g = & job - > gathers [ i ] ;
u32 * mapped ;
if ( job - > gather_copy_mapped )
mapped = ( u32 * ) job - > gather_copy_mapped ;
else
mapped = host1x_bo_mmap ( g - > bo ) ;
if ( ! mapped ) {
host1x_debug_output ( o , " [could not mmap] \n " ) ;
continue ;
}
2014-06-12 13:24:17 +02:00
host1x_debug_output ( o , " GATHER at %pad+%#x, %d words \n " ,
& g - > base , g - > offset , g - > words ) ;
2013-03-22 16:34:04 +02:00
show_gather ( o , g - > base + g - > offset , g - > words , cdma ,
g - > base , mapped ) ;
if ( ! job - > gather_copy_mapped )
host1x_bo_munmap ( g - > bo , mapped ) ;
}
}
}
2017-09-05 11:43:05 +03:00
# if HOST1X_HW >= 6
# include "debug_hw_1x06.c"
# else
# include "debug_hw_1x01.c"
# endif
2013-03-22 16:34:04 +02:00
static const struct host1x_debug_ops host1x_debug_ops = {
. show_channel_cdma = host1x_debug_show_channel_cdma ,
. show_channel_fifo = host1x_debug_show_channel_fifo ,
. show_mlocks = host1x_debug_show_mlocks ,
} ;