diff --git a/drivers/gpu/drm/img-rogue/gpu_trace_point.h b/drivers/gpu/drm/img-rogue/gpu_trace_point.h new file mode 100644 index 000000000..63b00d20d --- /dev/null +++ b/drivers/gpu/drm/img-rogue/gpu_trace_point.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#undef TRACE_SYSTEM +#define TRACE_SYSTEM gpu_trace_point + +#if !defined(_TRACE_GPU_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_GPU_H + +#include +#include +#include + +TRACE_EVENT(gpu_interrupt, + + TP_PROTO(unsigned int IRQStatusReg, unsigned int IRQStatus), + + TP_ARGS(IRQStatusReg, IRQStatus), + + TP_STRUCT__entry( + __field( unsigned int, IRQStatusReg) + __field( unsigned int, IRQStatus) + ), + + TP_fast_assign( + __entry->IRQStatusReg = IRQStatusReg; + __entry->IRQStatus = IRQStatus; + ), + + TP_printk("IRQStatusReg=%d IRQStatus=%d", __entry->IRQStatusReg, __entry->IRQStatus) +); + +#endif /* _TRACE_GPU_H */ + +/* This part must be outside protection */ +#include \ No newline at end of file diff --git a/drivers/gpu/drm/img-rogue/module_common.c b/drivers/gpu/drm/img-rogue/module_common.c index bf01dadbc..aa7ace0da 100644 --- a/drivers/gpu/drm/img-rogue/module_common.c +++ b/drivers/gpu/drm/img-rogue/module_common.c @@ -550,6 +550,14 @@ out: return iErr; } +static void wrap_pvr_sync_close(void *connection_data) +{ + CONNECTION_DATA *psConnection = (CONNECTION_DATA *)connection_data; + pvr_sync_close(connection_data); + OSConnectionPrivateDataDeInit(psConnection->hOsPrivateData); + kfree(psConnection); +} + /**************************************************************************/ /*! @Function PVRSRVDeviceSyncOpen @Description Sync device open. @@ -633,7 +641,7 @@ static int PVRSRVDeviceSyncOpen(PVRSRV_DEVICE_NODE *psDeviceNode, #if defined(SUPPORT_NATIVE_FENCE_SYNC) && !defined(USE_PVRSYNC_DEVNODE) #if (PVRSRV_DEVICE_INIT_MODE == PVRSRV_LINUX_DEV_INIT_ON_CONNECT) - psConnectionPriv->pfDeviceRelease = pvr_sync_close; + psConnectionPriv->pfDeviceRelease = wrap_pvr_sync_close; #endif #endif psDRMFile->driver_priv = psConnectionPriv; diff --git a/drivers/gpu/drm/img-rogue/osfunc.c b/drivers/gpu/drm/img-rogue/osfunc.c index 4c509adb4..d4eb97310 100644 --- a/drivers/gpu/drm/img-rogue/osfunc.c +++ b/drivers/gpu/drm/img-rogue/osfunc.c @@ -1843,6 +1843,34 @@ void OSDumpVersionInfo(DUMPDEBUG_PRINTF_FUNC *pfnDumpDebugPrintf, utsname()->version, utsname()->machine); } + +void OSWriteHWRegl(volatile void *pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT32 ui32Value) +{ + writel((IMG_UINT32)(ui32Value), (IMG_BYTE __iomem *)(pvLinRegBaseAddr) + (ui32Offset)); +} + +void OSWriteHWRegll(volatile void *pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT64 ui64Value) +{ + volatile void *_addr = pvLinRegBaseAddr; + IMG_UINT32 _off = ui32Offset; + IMG_UINT64 _val = ui64Value; + writel((IMG_UINT32)((_val) & 0xffffffff), (IMG_BYTE __iomem *)(_addr) + (_off)); + writel((IMG_UINT32)(((IMG_UINT64)(_val) >> 32) & 0xffffffff), (IMG_BYTE __iomem *)(_addr) + (_off) + 4); +} + +IMG_UINT32 OSReadHWRegl(volatile void *pvLinRegBaseAddr, IMG_UINT32 ui32Offset) +{ + return ((IMG_UINT32)readl((IMG_BYTE __iomem *)(pvLinRegBaseAddr) + (ui32Offset))); +} + +IMG_UINT64 OSReadHWRegll(volatile void *pvLinRegBaseAddr, IMG_UINT32 ui32Offset) +{ + volatile void *_addr = pvLinRegBaseAddr; + IMG_UINT32 _off = ui32Offset; + return (IMG_UINT64)(( (IMG_UINT64)(readl((IMG_BYTE __iomem *)(_addr) + (_off) + 4)) << 32) \ + | readl((IMG_BYTE __iomem *)(_addr) + (_off))); +} + #if defined(SUPPORT_DMA_TRANSFER) typedef struct _OS_CLEANUP_DATA_ diff --git a/drivers/gpu/drm/img-rogue/osfunc.h b/drivers/gpu/drm/img-rogue/osfunc.h index 93a94c40c..f5bfebe2a 100644 --- a/drivers/gpu/drm/img-rogue/osfunc.h +++ b/drivers/gpu/drm/img-rogue/osfunc.h @@ -1022,34 +1022,24 @@ void OSWriteMemoryBarrier(volatile void *hReadback); } while (0) #if defined(__linux__) && defined(__KERNEL__) && !defined(NO_HARDWARE) + + void OSWriteHWRegl(volatile void *pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT32 ui32Value); + void OSWriteHWRegll(volatile void *pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT64 ui64Value); + IMG_UINT32 OSReadHWRegl(volatile void *pvLinRegBaseAddr, IMG_UINT32 ui32Offset); + IMG_UINT64 OSReadHWRegll(volatile void *pvLinRegBaseAddr, IMG_UINT32 ui32Offset); + #define OSReadHWReg8(addr, off) ((IMG_UINT8)readb((IMG_BYTE __iomem *)(addr) + (off))) #define OSReadHWReg16(addr, off) ((IMG_UINT16)readw((IMG_BYTE __iomem *)(addr) + (off))) - #define OSReadHWReg32(addr, off) ((IMG_UINT32)readl((IMG_BYTE __iomem *)(addr) + (off))) + #define OSReadHWReg32(addr, off) OSReadHWRegl(addr, off) /* Little endian support only */ - #define OSReadHWReg64(addr, off) \ - ({ \ - __typeof__(addr) _addr = addr; \ - __typeof__(off) _off = off; \ - (IMG_UINT64) \ - ( \ - ( (IMG_UINT64)(readl((IMG_BYTE __iomem *)(_addr) + (_off) + 4)) << 32) \ - | readl((IMG_BYTE __iomem *)(_addr) + (_off)) \ - ); \ - }) + #define OSReadHWReg64(addr, off) OSReadHWRegll(addr, off) #define OSWriteHWReg8(addr, off, val) writeb((IMG_UINT8)(val), (IMG_BYTE __iomem *)(addr) + (off)) #define OSWriteHWReg16(addr, off, val) writew((IMG_UINT16)(val), (IMG_BYTE __iomem *)(addr) + (off)) - #define OSWriteHWReg32(addr, off, val) writel((IMG_UINT32)(val), (IMG_BYTE __iomem *)(addr) + (off)) + #define OSWriteHWReg32(addr, off, val) OSWriteHWRegl(addr, off, val) /* Little endian support only */ - #define OSWriteHWReg64(addr, off, val) do \ - { \ - __typeof__(addr) _addr = addr; \ - __typeof__(off) _off = off; \ - __typeof__(val) _val = val; \ - writel((IMG_UINT32)((_val) & 0xffffffff), (IMG_BYTE __iomem *)(_addr) + (_off)); \ - writel((IMG_UINT32)(((IMG_UINT64)(_val) >> 32) & 0xffffffff), (IMG_BYTE __iomem *)(_addr) + (_off) + 4); \ - } while (0) + #define OSWriteHWReg64(addr, off, val) OSWriteHWRegll(addr, off, val) #elif defined(NO_HARDWARE) diff --git a/drivers/gpu/drm/img-rogue/rgxinit.c b/drivers/gpu/drm/img-rogue/rgxinit.c index f01431c2e..cde6055cc 100644 --- a/drivers/gpu/drm/img-rogue/rgxinit.c +++ b/drivers/gpu/drm/img-rogue/rgxinit.c @@ -127,6 +127,10 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "pdump_physmem.h" #endif +#undef linux +#define CREATE_TRACE_POINTS +#include "gpu_trace_point.h" + static PVRSRV_ERROR RGXDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode); static PVRSRV_ERROR RGXDevVersionString(PVRSRV_DEVICE_NODE *psDeviceNode, IMG_CHAR **ppszVersionString); static PVRSRV_ERROR RGXDevClockSpeed(PVRSRV_DEVICE_NODE *psDeviceNode, IMG_PUINT32 pui32RGXClockSpeed); @@ -402,6 +406,7 @@ static inline IMG_BOOL RGXAckHwIrq(PVRSRV_RGXDEV_INFO *psDevInfo, { IMG_UINT32 ui32IRQStatus = OSReadHWReg32(psDevInfo->pvRegsBaseKM, ui32IRQStatusReg); + trace_gpu_interrupt(ui32IRQStatusReg, ui32IRQStatus); if (ui32IRQStatus & ui32IRQStatusEventMsk) { /* acknowledge and clear the interrupt */ @@ -511,6 +516,9 @@ static IMG_BOOL RGX_LISRHandler(void *pvData) { UPDATE_LISR_DBG_STATUS(RGX_LISR_DEVICE_NOT_POWERED); } + /* When handling interrupts, there may be a situation where the GPU is powered off, + * return IMG_TRUE to avoid the OS considering that this interrupt is nobody cared */ + bIrqAcknowledged = IMG_TRUE; } return bIrqAcknowledged; diff --git a/drivers/gpu/drm/img-rogue/server_srvcore_bridge.c b/drivers/gpu/drm/img-rogue/server_srvcore_bridge.c index 48abd121f..6fda53ff8 100644 --- a/drivers/gpu/drm/img-rogue/server_srvcore_bridge.c +++ b/drivers/gpu/drm/img-rogue/server_srvcore_bridge.c @@ -373,7 +373,7 @@ PVRSRVBridgeEventObjectClose(IMG_UINT32 ui32DispatchTableEntry, (psEventObjectCloseOUT->eError != PVRSRV_ERROR_KERNEL_CCB_FULL) && (psEventObjectCloseOUT->eError != PVRSRV_ERROR_RETRY))) { - PVR_DPF((PVR_DBG_ERROR, + PVR_DPF((PVR_DBG_WARNING, "%s: %s", __func__, PVRSRVGetErrorString(psEventObjectCloseOUT->eError))); UnlockHandle(psConnection->psHandleBase); goto EventObjectClose_exit; diff --git a/drivers/gpu/drm/img-rogue/sysconfig.c b/drivers/gpu/drm/img-rogue/sysconfig.c index bd623d5d6..a267925e2 100644 --- a/drivers/gpu/drm/img-rogue/sysconfig.c +++ b/drivers/gpu/drm/img-rogue/sysconfig.c @@ -307,6 +307,8 @@ PVRSRV_ERROR SysDevInit(void *pvOSDevice, PVRSRV_DEVICE_CONFIG **ppsDevConfig) dma_set_mask(pvOSDevice, DMA_BIT_MASK(40)); #endif + thead_sysfs_init(pvOSDevice); + mfg = dt_hw_init(pvOSDevice); if (IS_ERR(mfg)) { if (PTR_ERR(mfg) == -EPROBE_DEFER) @@ -419,6 +421,7 @@ void SysDevDeInit(PVRSRV_DEVICE_CONFIG *psDevConfig) #endif PhysHeapsDestroy(psDevConfig->pasPhysHeaps); + thead_sysfs_uninit(psDevConfig->pvOSDevice); OSFreeMem(psDevConfig); } diff --git a/drivers/gpu/drm/img-rogue/thead_sys.c b/drivers/gpu/drm/img-rogue/thead_sys.c index cd07a93c1..c838cde5c 100644 --- a/drivers/gpu/drm/img-rogue/thead_sys.c +++ b/drivers/gpu/drm/img-rogue/thead_sys.c @@ -54,9 +54,340 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include #include #include +#include +#include +#include +#include +#include +#include +#include "pvrsrv.h" +#include "pvr_drv.h" +#include "proc_stats.h" +#include "pvrversion.h" +#include "rgxhwperf.h" +#include "rgxinit.h" +#include "process_stats.h" #include "thead_sys.h" +#ifdef SUPPORT_RGX +static IMG_HANDLE ghGpuUtilSysFS; +#endif +static int thead_gpu_period_ms = -1; +static int thead_gpu_loading_max_percent = -1; +static int thead_gpu_last_server_error = 0; +static int thead_gpu_last_rgx_error = 0; + +struct gpu_sysfs_private_data { + struct device *dev; + struct timer_list timer; + struct workqueue_struct *workqueue; + struct work_struct work; +}; +static struct gpu_sysfs_private_data thead_gpu_sysfs_private_data; + +/******************定义log的读写属性*************************************/ +static ssize_t thead_gpu_log_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) +{ + ssize_t len = 0; + PDLLIST_NODE pNext, pNode; + struct device *dev = kobj_to_dev(kobj); + struct drm_device *drm_dev = dev_get_drvdata(dev); + struct pvr_drm_private *priv = drm_dev->dev_private; + PVRSRV_DEVICE_NODE *psDevNode = priv->dev_node; + PVRSRV_DEVICE_HEALTH_STATUS eHealthStatus = OSAtomicRead(&psDevNode->eHealthStatus); + PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData(); + + // 驱动信息 + int dev_id = (int)psDevNode->sDevId.ui32InternalID; + int dev_connection_num = 0; + int dev_loading_percent = -1; + + // 内存信息 + IMG_UINT32 dev_mem_state[PVRSRV_DRIVER_STAT_TYPE_COUNT]; + + // 实例/会话/通道信息 + int instance_id = 0; + + // 异常信息 + char* server_state[3] = {"UNDEFINED", "OK", "BAD"}; + char* rgx_state[5] = {"UNDEFINED", "OK", "NOT RESPONDING", "DEAD", "FAULT"}; + int rgx_err = 0; + + if (psDevNode->pvDevice != NULL) + { + PVRSRV_RGXDEV_INFO *psDevInfo = psDevNode->pvDevice; +#ifdef SUPPORT_RGX + if (!PVRSRV_VZ_MODE_IS(GUEST) && + psDevInfo->pfnGetGpuUtilStats && + eHealthStatus == PVRSRV_DEVICE_HEALTH_STATUS_OK) + { + RGXFWIF_GPU_UTIL_STATS sGpuUtilStats; + PVRSRV_ERROR eError = PVRSRV_OK; + + eError = psDevInfo->pfnGetGpuUtilStats(psDevNode, + ghGpuUtilSysFS, + &sGpuUtilStats); + + if ((eError == PVRSRV_OK) && + ((IMG_UINT32)sGpuUtilStats.ui64GpuStatCumulative)) + { + IMG_UINT64 util; + IMG_UINT32 rem; + + util = 100 * sGpuUtilStats.ui64GpuStatActive; + util = OSDivide64(util, (IMG_UINT32)sGpuUtilStats.ui64GpuStatCumulative, &rem); + + dev_loading_percent = (int)util; + } + } +#endif + rgx_err = psDevInfo->sErrorCounts.ui32WGPErrorCount + psDevInfo->sErrorCounts.ui32TRPErrorCount; + } + + if (dev_loading_percent > thead_gpu_loading_max_percent) + thead_gpu_loading_max_percent = dev_loading_percent; + + PVRSRVFindProcessMemStats(0, PVRSRV_DRIVER_STAT_TYPE_COUNT, IMG_TRUE, dev_mem_state); + + if (!psDevNode->hConnectionsLock) + { + len += scnprintf(buf + len, PAGE_SIZE - len, + "[GPU] Version: %s\n" + "Build Info: %s %s %s %s\n" + "----------------------------------------MODULE PARAM-----------------------------------------\n" + "updatePeriod_ms\n" + "%d\n" + "----------------------------------------MODULE STATUS----------------------------------------\n" + "DevId DevInstanceNum DevLoading_%% DevLoadingMax_%%\n" + "%-10d%-20d%-15d%-15d\n" + "----------------------------------------MEM INFO(KB)-----------------------------------------\n" + "KMalloc VMalloc PTMemoryUMA VMapPTUMA\n" + "%-18d%-18d%-18d%-18d\n" + "PTMemoryLMA IORemapPTLMA GPUMemLMA GPUMemUMA\n" + "%-18d%-18d%-18d%-18d\n" + "GPUMemUMAPool MappedGPUMemUMA/LMA DmaBufImport\n" + "%-18d%-36d%-18d\n" + "----------------------------------------INSTANCE INFO----------------------------------------\n" + "Id ProName ProId ThdId\n" + "---------------------------------------EXCEPTION INFO----------------------------------------\n" + "Server_State Server_Error RGX_State RGX_Error\n" + "%-18s%-18d%-18s%-18d\n", + PVRVERSION_STRING, utsname()->sysname, utsname()->release, utsname()->version, utsname()->machine, thead_gpu_period_ms, + dev_id, 0, dev_loading_percent, thead_gpu_loading_max_percent, + dev_mem_state[PVRSRV_DRIVER_STAT_TYPE_KMALLOC] >> 10, dev_mem_state[PVRSRV_DRIVER_STAT_TYPE_VMALLOC], + dev_mem_state[PVRSRV_DRIVER_STAT_TYPE_ALLOC_PT_MEMORY_UMA] >> 10, dev_mem_state[PVRSRV_DRIVER_STAT_TYPE_VMAP_PT_UMA] >> 10, + dev_mem_state[PVRSRV_DRIVER_STAT_TYPE_ALLOC_PT_MEMORY_LMA] >> 10, dev_mem_state[PVRSRV_DRIVER_STAT_TYPE_IOREMAP_PT_LMA] >> 10, + dev_mem_state[PVRSRV_DRIVER_STAT_TYPE_ALLOC_GPUMEM_LMA] >> 10, dev_mem_state[PVRSRV_DRIVER_STAT_TYPE_ALLOC_GPUMEM_UMA] >> 10, + dev_mem_state[PVRSRV_DRIVER_STAT_TYPE_ALLOC_GPUMEM_UMA_POOL] >> 10, dev_mem_state[PVRSRV_DRIVER_STAT_TYPE_MAPPED_GPUMEM_UMA_LMA] >> 10, + dev_mem_state[PVRSRV_DRIVER_STAT_TYPE_DMA_BUF_IMPORT] >> 10, + server_state[psPVRSRVData->eServicesState], PVRSRV_KM_ERRORS - thead_gpu_last_server_error, + rgx_state[eHealthStatus], rgx_err - thead_gpu_last_rgx_error); + return len; + } + + OSLockAcquire(psDevNode->hConnectionsLock); + dllist_foreach_node(&psDevNode->sConnections, pNode, pNext) + { + dev_connection_num++; + } + + // 格式化输出 + len += scnprintf(buf + len, PAGE_SIZE - len, + "[GPU] Version: %s\n" + "Build Info: %s %s %s %s\n" + "----------------------------------------MODULE PARAM-----------------------------------------\n" + "updatePeriod_ms\n" + "%d\n" + "----------------------------------------MODULE STATUS----------------------------------------\n" + "DevId DevInstanceNum DevLoading_%% DevLoadingMax_%%\n" + "%-10d%-20d%-15d%-15d\n" + "----------------------------------------MEM INFO(KB)-----------------------------------------\n" + "KMalloc VMalloc PTMemoryUMA VMapPTUMA\n" + "%-18d%-18d%-18d%-18d\n" + "PTMemoryLMA IORemapPTLMA GPUMemLMA GPUMemUMA\n" + "%-18d%-18d%-18d%-18d\n" + "GPUMemUMAPool MappedGPUMemUMA/LMA DmaBufImport\n" + "%-18d%-36d%-18d\n" + "----------------------------------------INSTANCE INFO----------------------------------------\n" + "Id ProName ProId ThdId\n", + PVRVERSION_STRING, utsname()->sysname, utsname()->release, utsname()->version, utsname()->machine, thead_gpu_period_ms, + dev_id, dev_connection_num, dev_loading_percent, thead_gpu_loading_max_percent, + dev_mem_state[PVRSRV_DRIVER_STAT_TYPE_KMALLOC] >> 10, dev_mem_state[PVRSRV_DRIVER_STAT_TYPE_VMALLOC], + dev_mem_state[PVRSRV_DRIVER_STAT_TYPE_ALLOC_PT_MEMORY_UMA] >> 10, dev_mem_state[PVRSRV_DRIVER_STAT_TYPE_VMAP_PT_UMA] >> 10, + dev_mem_state[PVRSRV_DRIVER_STAT_TYPE_ALLOC_PT_MEMORY_LMA] >> 10, dev_mem_state[PVRSRV_DRIVER_STAT_TYPE_IOREMAP_PT_LMA] >> 10, + dev_mem_state[PVRSRV_DRIVER_STAT_TYPE_ALLOC_GPUMEM_LMA] >> 10, dev_mem_state[PVRSRV_DRIVER_STAT_TYPE_ALLOC_GPUMEM_UMA] >> 10, + dev_mem_state[PVRSRV_DRIVER_STAT_TYPE_ALLOC_GPUMEM_UMA_POOL] >> 10, dev_mem_state[PVRSRV_DRIVER_STAT_TYPE_MAPPED_GPUMEM_UMA_LMA] >> 10, + dev_mem_state[PVRSRV_DRIVER_STAT_TYPE_DMA_BUF_IMPORT] >> 10); + + dllist_foreach_node(&psDevNode->sConnections, pNode, pNext) + { + CONNECTION_DATA *sData = IMG_CONTAINER_OF(pNode, CONNECTION_DATA, sConnectionListNode); + len += scnprintf(buf + len, PAGE_SIZE - len, + "%-5d%-20s%-10d%-10d\n", + instance_id, sData->pszProcName, sData->pid, sData->tid); + instance_id++; + } + + len += scnprintf(buf + len, PAGE_SIZE - len, + "---------------------------------------EXCEPTION INFO----------------------------------------\n" + "Server_State Server_Error RGX_State RGX_Error\n" + "%-18s%-18d%-18s%-18d\n", + server_state[psPVRSRVData->eServicesState], PVRSRV_KM_ERRORS - thead_gpu_last_server_error, + rgx_state[eHealthStatus], rgx_err - thead_gpu_last_rgx_error); + + OSLockRelease(psDevNode->hConnectionsLock); + return len; +} + +static ssize_t thead_gpu_log_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) +{ + struct device *dev = kobj_to_dev(kobj); + struct drm_device *drm_dev = dev_get_drvdata(dev); + struct pvr_drm_private *priv = drm_dev->dev_private; + PVRSRV_DEVICE_NODE *psDevNode = priv->dev_node; + + thead_gpu_loading_max_percent = -1; + thead_gpu_last_server_error = PVRSRV_KM_ERRORS; + if (psDevNode->pvDevice != NULL) + { + PVRSRV_RGXDEV_INFO *psDevInfo = psDevNode->pvDevice; + thead_gpu_last_rgx_error = psDevInfo->sErrorCounts.ui32WGPErrorCount + psDevInfo->sErrorCounts.ui32TRPErrorCount; + } + return count; +} + +static struct kobj_attribute sthead_gpu_log_attr = __ATTR(log, 0664, thead_gpu_log_show, thead_gpu_log_store); + +/******************定义updatePeriod的读写属性*************************************/ +static ssize_t thead_gpu_updatePeriod_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) +{ + return sprintf(buf, "%d\n(set 50~10000 to enable update period, set other value to disable)\n", + thead_gpu_period_ms); +} + +static ssize_t thead_gpu_updatePeriod_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) +{ + char *start = (char *)buf; + int temp_period_ms = simple_strtoul(start, &start, 0); + if (temp_period_ms >= 50 && temp_period_ms <= 10000) { + thead_gpu_period_ms = temp_period_ms; + mod_timer(&thead_gpu_sysfs_private_data.timer, jiffies + msecs_to_jiffies(thead_gpu_period_ms)); + } else { + thead_gpu_period_ms = -1; + del_timer(&thead_gpu_sysfs_private_data.timer); + } + return count; +} + +static struct kobj_attribute sthead_gpu_updateperiod_attr = __ATTR(updatePeriod_ms, 0664, thead_gpu_updatePeriod_show, thead_gpu_updatePeriod_store); + +/******************定义sysfs属性info group*************************************/ +static struct attribute *pthead_gpu_attrs[] = { + &sthead_gpu_log_attr.attr, + &sthead_gpu_updateperiod_attr.attr, + NULL, // must be NULL +}; + +static struct attribute_group sthead_gpu_attr_group = { + .name = "info", // device下目录指定 + .attrs = pthead_gpu_attrs, +}; + +static void thead_gpu_work_func(struct work_struct *w) +{ + struct gpu_sysfs_private_data *data = container_of(w, struct gpu_sysfs_private_data, work); + struct device *dev = data->dev; + struct drm_device *drm_dev = dev_get_drvdata(dev); + struct pvr_drm_private *priv = drm_dev->dev_private; + PVRSRV_DEVICE_NODE *psDevNode = priv->dev_node; + PVRSRV_DEVICE_HEALTH_STATUS eHealthStatus = OSAtomicRead(&psDevNode->eHealthStatus); + int current_loading_percent = -1; + if (psDevNode->pvDevice != NULL) + { + PVRSRV_RGXDEV_INFO *psDevInfo = psDevNode->pvDevice; +#ifdef SUPPORT_RGX + if (!PVRSRV_VZ_MODE_IS(GUEST) && + psDevInfo->pfnGetGpuUtilStats && + eHealthStatus == PVRSRV_DEVICE_HEALTH_STATUS_OK) + { + RGXFWIF_GPU_UTIL_STATS sGpuUtilStats; + PVRSRV_ERROR eError = PVRSRV_OK; + + eError = psDevInfo->pfnGetGpuUtilStats(psDevNode, + ghGpuUtilSysFS, + &sGpuUtilStats); + + if ((eError == PVRSRV_OK) && + ((IMG_UINT32)sGpuUtilStats.ui64GpuStatCumulative)) + { + IMG_UINT64 util; + IMG_UINT32 rem; + + util = 100 * sGpuUtilStats.ui64GpuStatActive; + util = OSDivide64(util, (IMG_UINT32)sGpuUtilStats.ui64GpuStatCumulative, &rem); + + current_loading_percent = (int)util; + } + } +#endif + } + if (current_loading_percent > thead_gpu_loading_max_percent) + thead_gpu_loading_max_percent = current_loading_percent; + mod_timer(&data->timer, jiffies + msecs_to_jiffies(thead_gpu_period_ms)); +} + +void thead_gpu_timer_callback(struct timer_list *t) +{ + struct gpu_sysfs_private_data *data = container_of(t, struct gpu_sysfs_private_data, timer); + queue_work(data->workqueue, &data->work); +} + +int thead_sysfs_init(struct device *dev) +{ + int ret; + ret = sysfs_create_group(&dev->kobj, &sthead_gpu_attr_group); + if (ret) { + dev_err(dev, "Failed to create gpu dev sysfs.\n"); + return ret; + } + +#if defined(SUPPORT_RGX) && !defined(NO_HARDWARE) + if (SORgxGpuUtilStatsRegister(&ghGpuUtilSysFS) != PVRSRV_OK) + { + dev_err(dev, "Failed to register GpuUtil for sysfs.\n"); + return -ENOMEM; + } +#endif + + thead_gpu_sysfs_private_data.workqueue = create_workqueue("gpu_sysfs_workqueue"); + if (!thead_gpu_sysfs_private_data.workqueue) + return -ENOMEM; + INIT_WORK(&thead_gpu_sysfs_private_data.work, thead_gpu_work_func); + + thead_gpu_sysfs_private_data.dev = dev; + timer_setup(&thead_gpu_sysfs_private_data.timer, thead_gpu_timer_callback, 0); + return ret; +} + +void thead_sysfs_uninit(struct device *dev) +{ + if (thead_gpu_sysfs_private_data.dev == dev) + del_timer(&thead_gpu_sysfs_private_data.timer); + + if (thead_gpu_sysfs_private_data.workqueue) + destroy_workqueue(thead_gpu_sysfs_private_data.workqueue); + +#if defined(SUPPORT_RGX) && !defined(NO_HARDWARE) + if (SORgxGpuUtilStatsUnregister(ghGpuUtilSysFS) != PVRSRV_OK) + { + dev_err(dev, "Failed to unregister GpuUtil for sysfs.\n"); + } +#endif + + sysfs_remove_group(&dev->kobj, &sthead_gpu_attr_group); +} + int thead_mfg_enable(struct gpu_plat_if *mfg) { int ret; diff --git a/drivers/gpu/drm/img-rogue/thead_sys.h b/drivers/gpu/drm/img-rogue/thead_sys.h index d514b0d6b..c563d3c97 100644 --- a/drivers/gpu/drm/img-rogue/thead_sys.h +++ b/drivers/gpu/drm/img-rogue/thead_sys.h @@ -63,6 +63,9 @@ struct gpu_plat_if { struct regmap *vosys_regmap; }; +int thead_sysfs_init(struct device *dev); +void thead_sysfs_uninit(struct device *dev); + struct gpu_plat_if *dt_hw_init(struct device *dev); void dt_hw_uninit(struct gpu_plat_if *mfg);