From: Luc Verhaegen Date: Tue, 22 Mar 2011 11:38:37 +0000 (+0100) Subject: gpu: pvr: debugfs: add hwrec edm trace X-Git-Url: http://git.openpandora.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6c1f2abe64100f4a1b5112fc593febe1c39eacdc;p=sgx.git gpu: pvr: debugfs: add hwrec edm trace And move all edm trace printing code to pvr_debugfs.c; since now only debugfs/pvr/edm_trace and debugfs/pvr/hwrec_edm use it. Signed-off-by: Luc Verhaegen Signed-off-by: Imre Deak --- diff --git a/pvr/pvr_debugfs.c b/pvr/pvr_debugfs.c index e5fb7a0..b9d32a3 100644 --- a/pvr/pvr_debugfs.c +++ b/pvr/pvr_debugfs.c @@ -110,38 +110,97 @@ static int pvr_debugfs_set(void *data, u64 val) DEFINE_SIMPLE_ATTRIBUTE(pvr_debugfs_fops, NULL, pvr_debugfs_set, "%llu\n"); +#ifdef PVRSRV_USSE_EDM_STATUS_DEBUG /* * */ +#define SGXMK_TRACE_BUFFER_SIZE 512 +#define SGXMK_TRACE_BUF_STR_LEN 80 + struct edm_buf_info { size_t len; char data[1]; }; -static int pvr_debugfs_edm_open(struct inode *inode, struct file *file) +static size_t +edm_trace_print(struct PVRSRV_SGXDEV_INFO *sdev, char *dst, size_t dst_len) +{ + u32 *buf_start; + u32 *buf_end; + u32 *buf; + size_t p = 0; + size_t wr_ofs; + int i; + + if (!sdev->psKernelEDMStatusBufferMemInfo) + return 0; + + buf = sdev->psKernelEDMStatusBufferMemInfo->pvLinAddrKM; + + p += snprintf(dst + p, dst_len - p, + "Last SGX microkernel status code: 0x%x\n", *buf); + buf++; + wr_ofs = *buf; + buf++; + + buf_start = buf; + buf_end = buf + SGXMK_TRACE_BUFFER_SIZE * 4; + + buf += wr_ofs * 4; + + /* Dump the status values */ + for (i = 0; i < SGXMK_TRACE_BUFFER_SIZE; i++) { + p += snprintf(dst + p, dst_len - p, "%3d %08X %08X %08X %08X\n", + i, buf[2], buf[3], buf[1], buf[0]); + buf += 4; + if (buf >= buf_end) + buf = buf_start; + } + + return p > dst_len ? dst_len : p; +} + +static struct edm_buf_info * +pvr_edm_buffer_create(struct PVRSRV_SGXDEV_INFO *sgx_info) { - struct PVRSRV_DEVICE_NODE *node; - struct PVRSRV_SGXDEV_INFO *sgx_info; struct edm_buf_info *bi; size_t size; /* Take a snapshot of the EDM trace buffer */ size = SGXMK_TRACE_BUFFER_SIZE * SGXMK_TRACE_BUF_STR_LEN; bi = vmalloc(sizeof(*bi) + size); - if (!bi) - return -ENOMEM; + if (!bi) { + pr_err("%s: vmalloc failed!\n", __func__); + return NULL; + } + + bi->len = edm_trace_print(sgx_info, bi->data, size); + + return bi; +} + +static void +pvr_edm_buffer_destroy(struct edm_buf_info *edm) +{ + vfree(edm); +} + +static int pvr_debugfs_edm_open(struct inode *inode, struct file *file) +{ + struct PVRSRV_DEVICE_NODE *node; node = get_sgx_node(); - sgx_info = node->pvDevice; - bi->len = snprint_edm_trace(sgx_info, bi->data, size); - file->private_data = bi; + + file->private_data = pvr_edm_buffer_create(node->pvDevice); + if (!file->private_data) + return -ENOMEM; return 0; } static int pvr_debugfs_edm_release(struct inode *inode, struct file *file) { - vfree(file->private_data); + pvr_edm_buffer_destroy(file->private_data); return 0; } @@ -160,7 +219,7 @@ static const struct file_operations pvr_debugfs_edm_fops = { .read = pvr_debugfs_edm_read, .release = pvr_debugfs_edm_release, }; - +#endif /* PVRSRV_USSE_EDM_STATUS_DEBUG */ /* * @@ -191,6 +250,10 @@ static size_t hwrec_mem_size; static unsigned long hwrec_mem_pages[HWREC_MEM_PAGES]; #endif /* CONFIG_PVR_DEBUG */ +#ifdef PVRSRV_USSE_EDM_STATUS_DEBUG +static struct edm_buf_info *hwrec_edm_buf; +#endif + static void hwrec_registers_dump(struct PVRSRV_SGXDEV_INFO *psDevInfo) { @@ -314,6 +377,12 @@ pvr_hwrec_dump(struct PVRSRV_SGXDEV_INFO *psDevInfo) mmu_hwrec_mem_dump(psDevInfo); #endif /* CONFIG_PVR_DEBUG */ +#ifdef PVRSRV_USSE_EDM_STATUS_DEBUG + if (hwrec_edm_buf) + pvr_edm_buffer_destroy(hwrec_edm_buf); + hwrec_edm_buf = pvr_edm_buffer_create(psDevInfo); +#endif + hwrec_event = 1; mutex_unlock(hwrec_mutex); @@ -605,6 +674,57 @@ static const struct file_operations hwrec_mem_fops = { }; #endif /* CONFIG_PVR_DEBUG */ +/* + * Read out edm trace created before HW recovery reset. + */ +#ifdef PVRSRV_USSE_EDM_STATUS_DEBUG +static loff_t +hwrec_edm_llseek(struct file *filp, loff_t offset, int whence) +{ + loff_t f_pos; + + mutex_lock(hwrec_mutex); + + if (hwrec_edm_buf) + f_pos = hwrec_llseek_helper(filp, offset, whence, + hwrec_edm_buf->len); + else + f_pos = 0; + + mutex_unlock(hwrec_mutex); + + return f_pos; +} + +static ssize_t +hwrec_edm_read(struct file *filp, char __user *buf, size_t size, + loff_t *f_pos) +{ + ssize_t ret; + + mutex_lock(hwrec_mutex); + + if (hwrec_edm_buf) + ret = simple_read_from_buffer(buf, size, f_pos, + hwrec_edm_buf->data, + hwrec_edm_buf->len); + else + ret = 0; + + mutex_unlock(hwrec_mutex); + + return ret; +} + +static const struct file_operations hwrec_edm_fops = { + .owner = THIS_MODULE, + .llseek = hwrec_edm_llseek, + .read = hwrec_edm_read, + .open = hwrec_file_open, + .release = hwrec_file_release, +}; +#endif /* PVRSRV_USSE_EDM_STATUS_DEBUG */ + /* * */ @@ -622,11 +742,13 @@ int pvr_debugfs_init(void) return -ENODEV; } +#ifdef PVRSRV_USSE_EDM_STATUS_DEBUG if (!debugfs_create_file("edm_trace", S_IRUGO, debugfs_dir, NULL, &pvr_debugfs_edm_fops)) { debugfs_remove_recursive(debugfs_dir); return -ENODEV; } +#endif if (!debugfs_create_file("hwrec_event", S_IRUSR, debugfs_dir, NULL, &hwrec_event_fops)) { @@ -654,6 +776,14 @@ int pvr_debugfs_init(void) } #endif /* CONFIG_PVR_DEBUG */ +#ifdef PVRSRV_USSE_EDM_STATUS_DEBUG + if (!debugfs_create_file("hwrec_edm", S_IRUSR, debugfs_dir, NULL, + &hwrec_edm_fops)) { + debugfs_remove_recursive(debugfs_dir); + return -ENODEV; + } +#endif + return 0; } @@ -668,4 +798,8 @@ void pvr_debugfs_cleanup(void) hwrec_mem_free(); #endif /* CONFIG_PVR_DEBUG */ +#ifdef PVRSRV_USSE_EDM_STATUS_DEBUG + if (hwrec_edm_buf) + pvr_edm_buffer_destroy(hwrec_edm_buf); +#endif } diff --git a/pvr/sgxinfokm.h b/pvr/sgxinfokm.h index 4191842..6722e0b 100644 --- a/pvr/sgxinfokm.h +++ b/pvr/sgxinfokm.h @@ -56,9 +56,6 @@ #define PVRSRV_USSE_MISCINFO_READY 0x1UL -#define SGXMK_TRACE_BUFFER_SIZE 512 -#define SGXMK_TRACE_BUF_STR_LEN 80 - struct PVRSRV_SGX_CCB_INFO; struct PVRSRV_SGXDEV_INFO { @@ -253,19 +250,6 @@ enum PVRSRV_ERROR SGXDevInitCompatCheck(struct PVRSRV_DEVICE_NODE void SysGetSGXTimingInformation(struct SGX_TIMING_INFORMATION *psSGXTimingInfo); -#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG) || defined(CONFIG_DEBUG_FS) -size_t snprint_edm_trace(struct PVRSRV_SGXDEV_INFO *sdev, char *buf, - size_t buf_size); -#else -static inline size_t snprint_edm_trace(struct PVRSRV_SGXDEV_INFO *sdev, - char *buf, size_t buf_size) -{ - return 0; -} -#endif - - - #if defined(NO_HARDWARE) static inline void NoHardwareGenerateEvent(struct PVRSRV_SGXDEV_INFO *psDevInfo, u32 ui32StatusRegister, diff --git a/pvr/sgxinit.c b/pvr/sgxinit.c index fcf4321..2b5612d 100644 --- a/pvr/sgxinit.c +++ b/pvr/sgxinit.c @@ -619,68 +619,6 @@ static enum PVRSRV_ERROR DevDeInitSGX(void *pvDeviceNode) return PVRSRV_OK; } -#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG) || defined(CONFIG_DEBUG_FS) - -static size_t __print_edm_trace(struct PVRSRV_SGXDEV_INFO *sdev, char *dst, - size_t dst_len) -{ - u32 *buf_start; - u32 *buf_end; - u32 *buf; - size_t p = 0; - size_t wr_ofs; - int i; - -#define _PR(fmt, ...) do { \ - if (dst) \ - p += snprintf(dst + p, dst_len - p, fmt, ## __VA_ARGS__); \ - else \ - printk(KERN_DEBUG fmt, ## __VA_ARGS__); \ -} while (0) - - if (!sdev->psKernelEDMStatusBufferMemInfo) - return 0; - - buf = sdev->psKernelEDMStatusBufferMemInfo->pvLinAddrKM; - - _PR("Last SGX microkernel status code: 0x%x\n", *buf); - buf++; - wr_ofs = *buf; - buf++; - - buf_start = buf; - buf_end = buf + SGXMK_TRACE_BUFFER_SIZE * 4; - - buf += wr_ofs * 4; - - /* Dump the status values */ - for (i = 0; i < SGXMK_TRACE_BUFFER_SIZE; i++) { - _PR("%3d %08X %08X %08X %08X\n", - i, buf[2], buf[3], buf[1], buf[0]); - buf += 4; - if (buf >= buf_end) - buf = buf_start; - } - - return p > dst_len ? dst_len : p; -#undef _PR -} - -size_t snprint_edm_trace(struct PVRSRV_SGXDEV_INFO *sdev, char *buf, - size_t buf_size) -{ - return __print_edm_trace(sdev, buf, buf_size); -} - -#endif - -static void dump_edm(struct PVRSRV_SGXDEV_INFO *sdev) -{ -#ifdef PVRSRV_USSE_EDM_STATUS_DEBUG - __print_edm_trace(sdev, NULL, 0); -#endif -} - static struct PVRSRV_PER_PROCESS_DATA *find_cur_proc_data( struct PVRSRV_DEVICE_NODE *dev) { @@ -988,7 +926,6 @@ void HWRecoveryResetSGX(struct PVRSRV_DEVICE_NODE *psDeviceNode) dump_process_info(psDeviceNode); dump_sgx_registers(psDevInfo); - dump_edm(psDevInfo); dump_sgx_state_bufs(psDeviceNode); #ifdef CONFIG_DEBUG_FS