diff options
Diffstat (limited to 'src/libXNVCtrlAttributes/NvCtrlAttributesNvml.c')
-rw-r--r-- | src/libXNVCtrlAttributes/NvCtrlAttributesNvml.c | 816 |
1 files changed, 613 insertions, 203 deletions
diff --git a/src/libXNVCtrlAttributes/NvCtrlAttributesNvml.c b/src/libXNVCtrlAttributes/NvCtrlAttributesNvml.c index d39f635..7cec7c8 100644 --- a/src/libXNVCtrlAttributes/NvCtrlAttributesNvml.c +++ b/src/libXNVCtrlAttributes/NvCtrlAttributesNvml.c @@ -192,14 +192,29 @@ static Bool LoadNvml(NvCtrlNvmlAttributes *nvml) GET_SYMBOL_REQUIRED(deviceGetUUID, "nvmlDeviceGetUUID"); GET_SYMBOL_REQUIRED(deviceGetCount, "nvmlDeviceGetCount"); GET_SYMBOL_REQUIRED(deviceGetTemperature, "nvmlDeviceGetTemperature"); - GET_SYMBOL_REQUIRED(deviceGetFanSpeed, "nvmlDeviceGetFanSpeed"); GET_SYMBOL_REQUIRED(deviceGetName, "nvmlDeviceGetName"); GET_SYMBOL_REQUIRED(deviceGetVbiosVersion, "nvmlDeviceGetVbiosVersion"); GET_SYMBOL_REQUIRED(deviceGetMemoryInfo, "nvmlDeviceGetMemoryInfo"); GET_SYMBOL_REQUIRED(deviceGetPciInfo, "nvmlDeviceGetPciInfo"); + GET_SYMBOL_REQUIRED(deviceGetCurrPcieLinkWidth, "nvmlDeviceGetCurrPcieLinkWidth"); GET_SYMBOL_REQUIRED(deviceGetMaxPcieLinkGeneration, "nvmlDeviceGetMaxPcieLinkGeneration"); GET_SYMBOL_REQUIRED(deviceGetMaxPcieLinkWidth, "nvmlDeviceGetMaxPcieLinkWidth"); GET_SYMBOL_REQUIRED(deviceGetVirtualizationMode, "nvmlDeviceGetVirtualizationMode"); + GET_SYMBOL_REQUIRED(deviceGetUtilizationRates, "nvmlDeviceGetUtilizationRates"); + GET_SYMBOL_REQUIRED(deviceGetTemperatureThreshold, "nvmlDeviceGetTemperatureThreshold"); + GET_SYMBOL_REQUIRED(deviceGetFanSpeed_v2, "nvmlDeviceGetFanSpeed_v2"); + GET_SYMBOL_REQUIRED(systemGetDriverVersion, "nvmlSystemGetDriverVersion"); + GET_SYMBOL_REQUIRED(deviceGetEccMode, "nvmlDeviceGetEccMode"); + GET_SYMBOL_REQUIRED(deviceSetEccMode, "nvmlDeviceSetEccMode"); + GET_SYMBOL_REQUIRED(deviceGetTotalEccErrors, "nvmlDeviceGetTotalEccErrors"); + GET_SYMBOL_REQUIRED(deviceClearEccErrorCounts, "nvmlDeviceClearEccErrorCounts"); + GET_SYMBOL_REQUIRED(systemGetNVMLVersion, "nvmlSystemGetNVMLVersion"); + GET_SYMBOL_REQUIRED(deviceGetMemoryErrorCounter, "nvmlDeviceGetMemoryErrorCounter"); + GET_SYMBOL_REQUIRED(deviceGetNumGpuCores, "nvmlDeviceGetNumGpuCores"); + GET_SYMBOL_REQUIRED(deviceGetMemoryBusWidth, "nvmlDeviceGetMemoryBusWidth"); + GET_SYMBOL_REQUIRED(deviceGetIrqNum, "nvmlDeviceGetIrqNum"); + GET_SYMBOL_REQUIRED(deviceGetPowerSource, "nvmlDeviceGetPowerSource"); + GET_SYMBOL_REQUIRED(deviceGetNumFans, "nvmlDeviceGetNumFans"); #undef GET_SYMBOL_REQUIRED /* Do not fail with older drivers */ @@ -207,6 +222,7 @@ static Bool LoadNvml(NvCtrlNvmlAttributes *nvml) nvml->lib._proc = dlsym(nvml->lib.handle, _name); GET_SYMBOL_OPTIONAL(deviceGetGridLicensableFeatures, "nvmlDeviceGetGridLicensableFeatures_v4"); + GET_SYMBOL_OPTIONAL(deviceGetMemoryInfo_v2, "nvmlDeviceGetMemoryInfo_v2"); #undef GET_SYMBOL_OPTIONAL ret = nvml->lib.init(); @@ -243,8 +259,8 @@ static Bool matchNvCtrlWithNvmlIds(const NvCtrlNvmlAttributes *nvml, int nvctrlGpuCount = 0; /* Get the gpu count returned by NV-CONTROL. */ - if (!XNVCTRLQueryTargetCount(h->dpy, NV_CTRL_TARGET_TYPE_GPU, - &nvctrlGpuCount)) { + if (h->nv && !XNVCTRLQueryTargetCount(h->dpy, NV_CTRL_TARGET_TYPE_GPU, + &nvctrlGpuCount)) { return FALSE; } @@ -367,7 +383,7 @@ NvCtrlNvmlAttributes *NvCtrlInitNvmlAttributes(NvCtrlAttributePrivateHandle *h) nvmlReturn_t ret = nvml->lib.deviceGetHandleByIndex(devIdx, &device); if (ret == NVML_SUCCESS) { unsigned int temp; - unsigned int speed; + unsigned int fans; /* * XXX Currently, NVML only allows to get the GPU temperature so @@ -387,12 +403,7 @@ NvCtrlNvmlAttributes *NvCtrlInitNvmlAttributes(NvCtrlAttributePrivateHandle *h) nvml->sensorCount++; } - /* - * XXX NVML assumes at most 1 fan per GPU so check for - * nvmlDeviceGetFanSpeed success to figure out if that fan is - * available. - */ - ret = nvml->lib.deviceGetFanSpeed(device, &speed); + ret = nvml->lib.deviceGetNumFans(device, &fans); if (ret == NVML_SUCCESS) { if ((h->target_type == COOLER_TARGET) && (h->target_id == nvml->coolerCount)) { @@ -400,21 +411,20 @@ NvCtrlNvmlAttributes *NvCtrlInitNvmlAttributes(NvCtrlAttributePrivateHandle *h) nvml->deviceIdx = devIdx; } - nvml->coolerCountPerGPU[i] = 1; - nvml->coolerCount++; + nvml->coolerCountPerGPU[i] = fans; + nvml->coolerCount += fans; } } } /* - * NVML doesn't have support to handle more than 1 fan per GPU. Make sure - * total number of cooler probed by NVML are same as that of reported by - * NV-CONTROL, otherwise do not initialize NVML sub-system. + * Consistency check between X/NV-CONTROL and NVML. */ - if (!XNVCTRLQueryTargetCount(h->dpy, NV_CTRL_TARGET_TYPE_COOLER, - &nvctrlCoolerCount) || - (nvctrlCoolerCount != nvml->coolerCount)) { - goto fail; + if (h->nv && + (!XNVCTRLQueryTargetCount(h->dpy, NV_CTRL_TARGET_TYPE_COOLER, + &nvctrlCoolerCount) || + (nvctrlCoolerCount != nvml->coolerCount))) { + nv_warning_msg("Inconsistent number of fans detected."); } nvfree(nvctrlToNvmlId); @@ -495,10 +505,50 @@ ReturnStatus NvCtrlNvmlQueryTargetCount(const CtrlTarget *ctrl_target, /* - * Get NVML String Attribute Values + * Get NVML String Attribute Values that do not require a control target. */ -#ifdef NVML_EXPERIMENTAL +static ReturnStatus NvCtrlNvmlGetGeneralStringAttribute(const CtrlTarget *ctrl_target, + int attr, char **ptr) +{ + char res[MAX_NVML_STR_LEN]; + const NvCtrlAttributePrivateHandle *h = getPrivateHandleConst(ctrl_target); + nvmlReturn_t ret; + *ptr = NULL; + + if ((h == NULL) || (h->nvml == NULL)) { + return NvCtrlBadHandle; + } + + switch (attr) { + case NV_CTRL_STRING_NVIDIA_DRIVER_VERSION: + ret = h->nvml->lib.systemGetDriverVersion(res, MAX_NVML_STR_LEN); + break; + + case NV_CTRL_STRING_NVML_VERSION: + ret = h->nvml->lib.systemGetNVMLVersion(res, MAX_NVML_STR_LEN); + break; + + default: + /* This is expected to fall through silently. */ + return NvCtrlNotSupported; + } + + if (ret == NVML_SUCCESS) { + *ptr = strdup(res); + return NvCtrlSuccess; + } + + /* An NVML error occurred */ + printNvmlError(ret); + return NvCtrlNotSupported; +} + + + +/* + * Get NVML String Attribute Values + */ static ReturnStatus NvCtrlNvmlGetGPUStringAttribute(const CtrlTarget *ctrl_target, int attr, char **ptr) @@ -531,11 +581,33 @@ static ReturnStatus NvCtrlNvmlGetGPUStringAttribute(const CtrlTarget *ctrl_targe ret = nvml->lib.deviceGetUUID(device, res, MAX_NVML_STR_LEN); break; - case NV_CTRL_STRING_NVIDIA_DRIVER_VERSION: + case NV_CTRL_STRING_GPU_UTILIZATION: + { + nvmlUtilization_t util; + + if (ctrl_target->system->has_nv_control) { + /* + * Not all utilization types are currently available via + * NVML so, if accessible, get the rates from X. + */ + return NvCtrlNotSupported; + } + + ret = nvml->lib.deviceGetUtilizationRates(device, &util); + + if (ret != NVML_SUCCESS) { + break; + } + + snprintf(res, sizeof(res), + "graphics=%d, memory=%d", + util.gpu, util.memory); + + break; + } case NV_CTRL_STRING_SLI_MODE: case NV_CTRL_STRING_PERFORMANCE_MODES: case NV_CTRL_STRING_GPU_CURRENT_CLOCK_FREQS: - case NV_CTRL_STRING_GPU_UTILIZATION: case NV_CTRL_STRING_MULTIGPU_MODE: /* * XXX We'll eventually need to add support for this attributes @@ -562,22 +634,26 @@ static ReturnStatus NvCtrlNvmlGetGPUStringAttribute(const CtrlTarget *ctrl_targe return NvCtrlNotSupported; } -#endif // NVML_EXPERIMENTAL + ReturnStatus NvCtrlNvmlGetStringAttribute(const CtrlTarget *ctrl_target, int attr, char **ptr) { + ReturnStatus ret; + if (NvmlMissing(ctrl_target)) { return NvCtrlMissingExtension; } -#ifdef NVML_EXPERIMENTAL /* - * This shouldn't be reached for target types that are not handled through - * NVML (Keep TARGET_TYPE_IS_NVML_COMPATIBLE in NvCtrlAttributesPrivate.h up - * to date). + * Check for attributes that don't require a target, else continue to + * supported target types. */ - assert(TARGET_TYPE_IS_NVML_COMPATIBLE(NvCtrlGetTargetType(ctrl_target))); + ret = NvCtrlNvmlGetGeneralStringAttribute(ctrl_target, attr, ptr); + + if (ret == NvCtrlSuccess) { + return NvCtrlSuccess; + } switch (NvCtrlGetTargetType(ctrl_target)) { case GPU_TARGET: @@ -600,10 +676,6 @@ ReturnStatus NvCtrlNvmlGetStringAttribute(const CtrlTarget *ctrl_target, default: return NvCtrlBadHandle; } - -#else - return NvCtrlNotSupported; -#endif } @@ -612,7 +684,7 @@ ReturnStatus NvCtrlNvmlGetStringAttribute(const CtrlTarget *ctrl_target, * Set NVML String Attribute Values */ -#ifdef NVML_EXPERIMENTAL + static ReturnStatus NvCtrlNvmlSetGPUStringAttribute(CtrlTarget *ctrl_target, int attr, const char *ptr) @@ -656,7 +728,7 @@ static ReturnStatus NvCtrlNvmlSetGPUStringAttribute(CtrlTarget *ctrl_target, return NvCtrlNotSupported; } -#endif // NVML_EXPERIMENTAL + ReturnStatus NvCtrlNvmlSetStringAttribute(CtrlTarget *ctrl_target, int attr, const char *ptr) @@ -665,7 +737,6 @@ ReturnStatus NvCtrlNvmlSetStringAttribute(CtrlTarget *ctrl_target, return NvCtrlMissingExtension; } -#ifdef NVML_EXPERIMENTAL /* * This shouldn't be reached for target types that are not handled through * NVML (Keep TARGET_TYPE_IS_NVML_COMPATIBLE in NvCtrlAttributesPrivate.h up @@ -695,10 +766,6 @@ ReturnStatus NvCtrlNvmlSetStringAttribute(CtrlTarget *ctrl_target, default: return NvCtrlBadHandle; } - -#else - return NvCtrlNotSupported; -#endif } @@ -710,7 +777,7 @@ ReturnStatus NvCtrlNvmlSetStringAttribute(CtrlTarget *ctrl_target, static ReturnStatus NvCtrlNvmlGetGPUAttribute(const CtrlTarget *ctrl_target, int attr, int64_t *val) { - unsigned int res; + unsigned int res = 0; const NvCtrlAttributePrivateHandle *h = getPrivateHandleConst(ctrl_target); const NvCtrlNvmlAttributes *nvml; nvmlDevice_t device; @@ -725,20 +792,35 @@ static ReturnStatus NvCtrlNvmlGetGPUAttribute(const CtrlTarget *ctrl_target, ret = nvml->lib.deviceGetHandleByIndex(nvml->deviceIdx, &device); if (ret == NVML_SUCCESS) { switch (attr) { -#ifdef NVML_EXPERIMENTAL case NV_CTRL_TOTAL_DEDICATED_GPU_MEMORY: case NV_CTRL_USED_DEDICATED_GPU_MEMORY: { - nvmlMemory_t memory; - ret = nvml->lib.deviceGetMemoryInfo(device, &memory); - if (ret == NVML_SUCCESS) { - switch (attr) { - case NV_CTRL_TOTAL_DEDICATED_GPU_MEMORY: - res = memory.total >> 20; // bytes --> MB - break; - case NV_CTRL_USED_DEDICATED_GPU_MEMORY: - res = memory.used >> 20; // bytes --> MB - break; + if (nvml->lib.deviceGetMemoryInfo_v2) { + nvmlMemory_v2_t memory; + memory.version = nvmlMemory_v2; + ret = nvml->lib.deviceGetMemoryInfo_v2(device, &memory); + if (ret == NVML_SUCCESS) { + switch (attr) { + case NV_CTRL_TOTAL_DEDICATED_GPU_MEMORY: + res = memory.total >> 20; // bytes --> MB + break; + case NV_CTRL_USED_DEDICATED_GPU_MEMORY: + res = memory.used >> 20; // bytes --> MB + break; + } + } + } else { + nvmlMemory_t memory; + ret = nvml->lib.deviceGetMemoryInfo(device, &memory); + if (ret == NVML_SUCCESS) { + switch (attr) { + case NV_CTRL_TOTAL_DEDICATED_GPU_MEMORY: + res = memory.total >> 20; // bytes --> MB + break; + case NV_CTRL_USED_DEDICATED_GPU_MEMORY: + res = memory.used >> 20; // bytes --> MB + break; + } } } } @@ -787,41 +869,127 @@ static ReturnStatus NvCtrlNvmlGetGPUAttribute(const CtrlTarget *ctrl_target, ret = nvml->lib.deviceGetMaxPcieLinkGeneration(device, &res); break; + case NV_CTRL_GPU_PCIE_CURRENT_LINK_WIDTH: + ret = nvml->lib.deviceGetCurrPcieLinkWidth(device, &res); + break; case NV_CTRL_GPU_PCIE_MAX_LINK_WIDTH: ret = nvml->lib.deviceGetMaxPcieLinkWidth(device, &res); break; -#else - case NV_CTRL_TOTAL_DEDICATED_GPU_MEMORY: - case NV_CTRL_USED_DEDICATED_GPU_MEMORY: - case NV_CTRL_PCI_DOMAIN: - case NV_CTRL_PCI_BUS: - case NV_CTRL_PCI_DEVICE: - case NV_CTRL_PCI_FUNCTION: - case NV_CTRL_PCI_ID: - case NV_CTRL_GPU_PCIE_GENERATION: - case NV_CTRL_GPU_PCIE_MAX_LINK_WIDTH: -#endif // NVML_EXPERIMENTAL + case NV_CTRL_GPU_SLOWDOWN_THRESHOLD: + ret = nvml->lib.deviceGetTemperatureThreshold(device, + NVML_TEMPERATURE_THRESHOLD_SLOWDOWN ,&res); + break; + case NV_CTRL_GPU_SHUTDOWN_THRESHOLD: + ret = nvml->lib.deviceGetTemperatureThreshold(device, + NVML_TEMPERATURE_THRESHOLD_SHUTDOWN ,&res); + break; + case NV_CTRL_GPU_CORE_TEMPERATURE: + ret = nvml->lib.deviceGetTemperature(device, + NVML_TEMPERATURE_GPU, + &res); + break; + + case NV_CTRL_GPU_ECC_CONFIGURATION_SUPPORTED: + case NV_CTRL_GPU_ECC_SUPPORTED: + { + nvmlEnableState_t current, pending; + ret = nvml->lib.deviceGetEccMode(device, ¤t, &pending); + switch (attr) { + case NV_CTRL_GPU_ECC_CONFIGURATION_SUPPORTED: + res = (ret == NVML_SUCCESS) ? + NV_CTRL_GPU_ECC_CONFIGURATION_SUPPORTED_TRUE : + NV_CTRL_GPU_ECC_CONFIGURATION_SUPPORTED_FALSE; + break; + case NV_CTRL_GPU_ECC_SUPPORTED: + res = (ret == NVML_SUCCESS) ? + NV_CTRL_GPU_ECC_SUPPORTED_TRUE : + NV_CTRL_GPU_ECC_SUPPORTED_FALSE; + break; + } + } + break; + + case NV_CTRL_GPU_ECC_CONFIGURATION: + case NV_CTRL_GPU_ECC_STATUS: + { + nvmlEnableState_t current, pending; + ret = nvml->lib.deviceGetEccMode(device, ¤t, &pending); + if (ret == NVML_SUCCESS) { + switch (attr) { + case NV_CTRL_GPU_ECC_STATUS: + res = current; + break; + case NV_CTRL_GPU_ECC_CONFIGURATION: + res = pending; + break; + } + } + } + break; + + case NV_CTRL_GPU_ECC_SINGLE_BIT_ERRORS: + case NV_CTRL_GPU_ECC_AGGREGATE_SINGLE_BIT_ERRORS: + case NV_CTRL_GPU_ECC_DOUBLE_BIT_ERRORS: + case NV_CTRL_GPU_ECC_AGGREGATE_DOUBLE_BIT_ERRORS: + { + unsigned long long eccCounts; + nvmlEccCounterType_t counterType; + nvmlMemoryErrorType_t errorType; + switch (attr) { + case NV_CTRL_GPU_ECC_SINGLE_BIT_ERRORS: + errorType = NVML_MEMORY_ERROR_TYPE_CORRECTED; + counterType = NVML_VOLATILE_ECC; + break; + case NV_CTRL_GPU_ECC_AGGREGATE_SINGLE_BIT_ERRORS: + errorType = NVML_MEMORY_ERROR_TYPE_CORRECTED; + counterType = NVML_AGGREGATE_ECC; + break; + case NV_CTRL_GPU_ECC_DOUBLE_BIT_ERRORS: + errorType = NVML_MEMORY_ERROR_TYPE_UNCORRECTED; + counterType = NVML_VOLATILE_ECC; + break; + case NV_CTRL_GPU_ECC_AGGREGATE_DOUBLE_BIT_ERRORS: + errorType = NVML_MEMORY_ERROR_TYPE_UNCORRECTED; + counterType = NVML_AGGREGATE_ECC; + break; + } + + ret = nvml->lib.deviceGetTotalEccErrors(device, errorType, + counterType, &eccCounts); + if (ret == NVML_SUCCESS) { + if (val) { + *val = eccCounts; + } + return NvCtrlSuccess; + } + } + break; + + case NV_CTRL_GPU_CORES: + ret = nvml->lib.deviceGetNumGpuCores(device, &res); + break; + case NV_CTRL_GPU_MEMORY_BUS_WIDTH: + ret = nvml->lib.deviceGetMemoryBusWidth(device, &res); + break; + case NV_CTRL_IRQ: + ret = nvml->lib.deviceGetIrqNum(device, &res); + break; + case NV_CTRL_GPU_POWER_SOURCE: + assert(NV_CTRL_GPU_POWER_SOURCE_AC == NVML_POWER_SOURCE_AC); + assert(NV_CTRL_GPU_POWER_SOURCE_BATTERY == NVML_POWER_SOURCE_BATTERY); + ret = nvml->lib.deviceGetPowerSource(device, &res); + break; + + case NV_CTRL_GPU_ECC_DEFAULT_CONFIGURATION: case NV_CTRL_VIDEO_RAM: - case NV_CTRL_GPU_PCIE_CURRENT_LINK_WIDTH: case NV_CTRL_GPU_PCIE_MAX_LINK_SPEED: case NV_CTRL_GPU_PCIE_CURRENT_LINK_SPEED: case NV_CTRL_BUS_TYPE: - case NV_CTRL_GPU_MEMORY_BUS_WIDTH: - case NV_CTRL_GPU_CORES: - case NV_CTRL_IRQ: case NV_CTRL_GPU_COOLER_MANUAL_CONTROL: - case NV_CTRL_GPU_POWER_SOURCE: case NV_CTRL_GPU_CURRENT_PERFORMANCE_LEVEL: case NV_CTRL_GPU_ADAPTIVE_CLOCK_STATE: case NV_CTRL_GPU_POWER_MIZER_MODE: case NV_CTRL_GPU_POWER_MIZER_DEFAULT_MODE: - case NV_CTRL_GPU_ECC_SUPPORTED: - case NV_CTRL_GPU_ECC_STATUS: - case NV_CTRL_GPU_ECC_CONFIGURATION: - case NV_CTRL_GPU_ECC_DEFAULT_CONFIGURATION: - case NV_CTRL_GPU_ECC_DOUBLE_BIT_ERRORS: - case NV_CTRL_GPU_ECC_AGGREGATE_DOUBLE_BIT_ERRORS: - case NV_CTRL_GPU_ECC_CONFIGURATION_SUPPORTED: case NV_CTRL_ENABLED_DISPLAYS: case NV_CTRL_CONNECTED_DISPLAYS: case NV_CTRL_MAX_SCREEN_WIDTH: @@ -836,10 +1004,8 @@ static ReturnStatus NvCtrlNvmlGetGPUAttribute(const CtrlTarget *ctrl_target, case NV_CTRL_ATTR_NV_MINOR_VERSION: case NV_CTRL_OPERATING_SYSTEM: case NV_CTRL_NO_SCANOUT: - case NV_CTRL_GPU_CORE_TEMPERATURE: case NV_CTRL_AMBIENT_TEMPERATURE: case NV_CTRL_GPU_CURRENT_CLOCK_FREQS: - case NV_CTRL_GPU_CURRENT_PROCESSOR_CLOCK_FREQS: case NV_CTRL_VIDEO_ENCODER_UTILIZATION: case NV_CTRL_VIDEO_DECODER_UTILIZATION: case NV_CTRL_FRAMELOCK: @@ -886,14 +1052,16 @@ static ReturnStatus NvCtrlNvmlGetGPUAttribute(const CtrlTarget *ctrl_target, default: /* Did we forget to handle a GPU integer attribute? */ - nv_warning_msg("Unhandled integer attribute %s (%d) of GPU " - "(%d)", INT_ATTRIBUTE_NAME(attr), attr, - NvCtrlGetTargetId(ctrl_target)); + nv_info_msg("", "Unhandled integer attribute %s (%d) of GPU " + "(%d)", INT_ATTRIBUTE_NAME(attr), attr, + NvCtrlGetTargetId(ctrl_target)); return NvCtrlNotSupported; } if (ret == NVML_SUCCESS) { - *val = res; + if (val) { + *val = res; + } return NvCtrlSuccess; } } @@ -951,7 +1119,7 @@ static ReturnStatus NvCtrlNvmlGetGridLicensableFeatures(const CtrlTarget *ctrl_t return NvCtrlNotSupported; } -#ifdef NVML_EXPERIMENTAL + static int getThermalCoolerId(const NvCtrlAttributePrivateHandle *h, unsigned int thermalCoolerCount, @@ -1003,11 +1171,7 @@ static ReturnStatus NvCtrlNvmlGetThermalAttribute(const CtrlTarget *ctrl_target, if (ret == NVML_SUCCESS) { switch (attr) { case NV_CTRL_THERMAL_SENSOR_READING: - ret = nvml->lib.deviceGetTemperature(device, - NVML_TEMPERATURE_GPU, - &res); - break; - + case NV_CTRL_THERMAL_SENSOR_PROVIDER: case NV_CTRL_THERMAL_SENSOR_TARGET: /* @@ -1018,9 +1182,9 @@ static ReturnStatus NvCtrlNvmlGetThermalAttribute(const CtrlTarget *ctrl_target, default: /* Did we forget to handle a sensor integer attribute? */ - nv_warning_msg("Unhandled integer attribute %s (%d) of " - "Thermal sensor (%d)", INT_ATTRIBUTE_NAME(attr), - attr, NvCtrlGetTargetId(ctrl_target)); + nv_info_msg("", "Unhandled integer attribute %s (%d) of " + "Thermal sensor (%d)", INT_ATTRIBUTE_NAME(attr), + attr, NvCtrlGetTargetId(ctrl_target)); return NvCtrlNotSupported; } @@ -1062,10 +1226,11 @@ static ReturnStatus NvCtrlNvmlGetCoolerAttribute(const CtrlTarget *ctrl_target, ret = nvml->lib.deviceGetHandleByIndex(nvml->deviceIdx, &device); if (ret == NVML_SUCCESS) { switch (attr) { - case NV_CTRL_THERMAL_COOLER_LEVEL: - ret = nvml->lib.deviceGetFanSpeed(device, &res); + case NV_CTRL_THERMAL_COOLER_CURRENT_LEVEL: + ret = nvml->lib.deviceGetFanSpeed_v2(device, coolerId, &res); break; + case NV_CTRL_THERMAL_COOLER_LEVEL: case NV_CTRL_THERMAL_COOLER_SPEED: case NV_CTRL_THERMAL_COOLER_CONTROL_TYPE: case NV_CTRL_THERMAL_COOLER_TARGET: @@ -1077,9 +1242,9 @@ static ReturnStatus NvCtrlNvmlGetCoolerAttribute(const CtrlTarget *ctrl_target, default: /* Did we forget to handle a cooler integer attribute? */ - nv_warning_msg("Unhandled integer attribute %s (%d) of Fan " - "(%d)", INT_ATTRIBUTE_NAME(attr), attr, - NvCtrlGetTargetId(ctrl_target)); + nv_info_msg("", "Unhandled integer attribute %s (%d) of Fan " + "(%d)", INT_ATTRIBUTE_NAME(attr), attr, + NvCtrlGetTargetId(ctrl_target)); return NvCtrlNotSupported; } @@ -1093,7 +1258,8 @@ static ReturnStatus NvCtrlNvmlGetCoolerAttribute(const CtrlTarget *ctrl_target, printNvmlError(ret); return NvCtrlNotSupported; } -#endif // NVML_EXPERIMENTAL + + ReturnStatus NvCtrlNvmlGetAttribute(const CtrlTarget *ctrl_target, int attr, int64_t *val) @@ -1112,18 +1278,12 @@ ReturnStatus NvCtrlNvmlGetAttribute(const CtrlTarget *ctrl_target, switch (NvCtrlGetTargetType(ctrl_target)) { case GPU_TARGET: return NvCtrlNvmlGetGPUAttribute(ctrl_target, attr, val); -#ifdef NVML_EXPERIMENTAL case THERMAL_SENSOR_TARGET: return NvCtrlNvmlGetThermalAttribute(ctrl_target, attr, val); case COOLER_TARGET: return NvCtrlNvmlGetCoolerAttribute(ctrl_target, attr, val); -#else - case THERMAL_SENSOR_TARGET: - case COOLER_TARGET: - return NvCtrlNotSupported; -#endif default: - return NvCtrlBadHandle; + return NvCtrlNotSupported; } } @@ -1155,7 +1315,7 @@ ReturnStatus NvCtrlNvmlGetGridLicenseAttributes(const CtrlTarget *ctrl_target, * Set NVML Attribute Values */ -#ifdef NVML_EXPERIMENTAL + static ReturnStatus NvCtrlNvmlSetGPUAttribute(CtrlTarget *ctrl_target, int attr, int index, int val) @@ -1174,9 +1334,28 @@ static ReturnStatus NvCtrlNvmlSetGPUAttribute(CtrlTarget *ctrl_target, ret = nvml->lib.deviceGetHandleByIndex(nvml->deviceIdx, &device); if (ret == NVML_SUCCESS) { switch (attr) { + case NV_CTRL_GPU_ECC_CONFIGURATION: + ret = nvml->lib.deviceSetEccMode(device, val); + break; + + case NV_CTRL_GPU_ECC_RESET_ERROR_STATUS: + { + nvmlEccCounterType_t counterType = 0; + switch (val) { + case NV_CTRL_GPU_ECC_RESET_ERROR_STATUS_VOLATILE: + counterType = NVML_VOLATILE_ECC; + break; + case NV_CTRL_GPU_ECC_RESET_ERROR_STATUS_AGGREGATE: + counterType = NVML_AGGREGATE_ECC; + break; + } + ret = nvml->lib.deviceClearEccErrorCounts(device, + counterType); + } + break; + case NV_CTRL_GPU_CURRENT_CLOCK_FREQS: case NV_CTRL_GPU_POWER_MIZER_MODE: - case NV_CTRL_GPU_ECC_CONFIGURATION: case NV_CTRL_GPU_COOLER_MANUAL_CONTROL: case NV_CTRL_DITHERING: case NV_CTRL_DITHERING_MODE: @@ -1193,9 +1372,9 @@ static ReturnStatus NvCtrlNvmlSetGPUAttribute(CtrlTarget *ctrl_target, default: /* Did we forget to handle a GPU integer attribute? */ - nv_warning_msg("Unhandled integer attribute %s (%d) of GPU " - "(%d) (set to %d)", INT_ATTRIBUTE_NAME(attr), - attr, NvCtrlGetTargetId(ctrl_target), val); + nv_info_msg("", "Unhandled integer attribute %s (%d) of GPU " + "(%d) (set to %d)", INT_ATTRIBUTE_NAME(attr), + attr, NvCtrlGetTargetId(ctrl_target), val); return NvCtrlNotSupported; } @@ -1244,9 +1423,9 @@ static ReturnStatus NvCtrlNvmlSetCoolerAttribute(CtrlTarget *ctrl_target, default: /* Did we forget to handle a cooler integer attribute? */ - nv_warning_msg("Unhandled integer attribute %s (%d) of Fan " - "(%d) (set to %d)", INT_ATTRIBUTE_NAME(attr), - attr, NvCtrlGetTargetId(ctrl_target), val); + nv_info_msg("", "Unhandled integer attribute %s (%d) of Fan " + "(%d) (set to %d)", INT_ATTRIBUTE_NAME(attr), + attr, NvCtrlGetTargetId(ctrl_target), val); return NvCtrlNotSupported; } @@ -1260,7 +1439,7 @@ static ReturnStatus NvCtrlNvmlSetCoolerAttribute(CtrlTarget *ctrl_target, return NvCtrlNotSupported; } -#endif // NVML_EXPERIMENTAL + ReturnStatus NvCtrlNvmlSetAttribute(CtrlTarget *ctrl_target, int attr, int index, int val) @@ -1269,7 +1448,6 @@ ReturnStatus NvCtrlNvmlSetAttribute(CtrlTarget *ctrl_target, int attr, return NvCtrlMissingExtension; } -#ifdef NVML_EXPERIMENTAL /* * This shouldn't be reached for target types that are not handled through * NVML (Keep TARGET_TYPE_IS_NVML_COMPATIBLE in NvCtrlAttributesPrivate.h up @@ -1283,9 +1461,9 @@ ReturnStatus NvCtrlNvmlSetAttribute(CtrlTarget *ctrl_target, int attr, case THERMAL_SENSOR_TARGET: /* Did we forget to handle a sensor integer attribute? */ - nv_warning_msg("Unhandled integer attribute %s (%d) of Thermal " - "sensor (%d) (set to %d)", INT_ATTRIBUTE_NAME(attr), - attr, NvCtrlGetTargetId(ctrl_target), val); + nv_info_msg("", "Unhandled integer attribute %s (%d) of Thermal " + "sensor (%d) (set to %d)", INT_ATTRIBUTE_NAME(attr), + attr, NvCtrlGetTargetId(ctrl_target), val); return NvCtrlNotSupported; case COOLER_TARGET: @@ -1293,19 +1471,47 @@ ReturnStatus NvCtrlNvmlSetAttribute(CtrlTarget *ctrl_target, int attr, default: return NvCtrlBadHandle; } - -#else - return NvCtrlNotSupported; -#endif } +static nvmlReturn_t getDeviceMemoryCounts(const CtrlTarget *ctrl_target, + const NvCtrlNvmlAttributes *nvml, + nvmlDevice_t device, + nvmlMemoryErrorType_t errorType, + nvmlEccCounterType_t counterType, + unsigned char **data, int *len) +{ + unsigned long long count; + int *counts = (int *) nvalloc(sizeof(int) * NVML_MEMORY_LOCATION_COUNT); + nvmlReturn_t ret, anySuccess = NVML_ERROR_NOT_SUPPORTED; + int i; + + for (i = NVML_MEMORY_LOCATION_L1_CACHE; + i < NVML_MEMORY_LOCATION_COUNT; + i++) { + + ret = nvml->lib.deviceGetMemoryErrorCounter(device, errorType, + counterType, i, &count); + if (ret == NVML_SUCCESS) { + anySuccess = NVML_SUCCESS; + counts[i] = (int) count; + } else { + counts[i] = -1; + } + } + + *data = (unsigned char *) counts; + *len = sizeof(int) * NVML_MEMORY_LOCATION_COUNT; + + return anySuccess; +} + /* * Get NVML Binary Attribute Values */ -#ifdef NVML_EXPERIMENTAL + static ReturnStatus NvCtrlNvmlGetGPUBinaryAttribute(const CtrlTarget *ctrl_target, @@ -1325,8 +1531,66 @@ NvCtrlNvmlGetGPUBinaryAttribute(const CtrlTarget *ctrl_target, ret = nvml->lib.deviceGetHandleByIndex(nvml->deviceIdx, &device); if (ret == NVML_SUCCESS) { switch (attr) { - case NV_CTRL_BINARY_DATA_FRAMELOCKS_USED_BY_GPU: case NV_CTRL_BINARY_DATA_COOLERS_USED_BY_GPU: + { + unsigned int *fan_data; + unsigned int count = 0; + int offset = 0; + int i = 0; + + ret = nvml->lib.deviceGetNumFans(device, &count); + if (ret != NVML_SUCCESS) { + return NvCtrlNotSupported; + } + + /* + * The format of the returned data is: + * + * int unsigned int number of COOLERS + * int * n unsigned int COOLER indices + */ + + *len = (count + 1) * sizeof(unsigned int); + fan_data = (unsigned int *) nvalloc(*len); + memset(fan_data, 0, *len); + *data = (unsigned char *) fan_data; + + /* Calculate global fan index offset for this GPU */ + for (i = 0; i < nvml->deviceIdx; i++) { + offset += nvml->coolerCountPerGPU[i]; + } + + fan_data[0] = count; + for (i = 0; i < count; i++) { + fan_data[i+1] = i + offset; + } + break; + } + case NV_CTRL_BINARY_DATA_GPU_ECC_DETAILED_ERRORS_SINGLE_BIT: + ret = getDeviceMemoryCounts(ctrl_target, nvml, device, + NVML_MEMORY_ERROR_TYPE_CORRECTED, + NVML_VOLATILE_ECC, + data, len); + break; + case NV_CTRL_BINARY_DATA_GPU_ECC_DETAILED_ERRORS_DOUBLE_BIT: + ret = getDeviceMemoryCounts(ctrl_target, nvml, device, + NVML_MEMORY_ERROR_TYPE_UNCORRECTED, + NVML_VOLATILE_ECC, + data, len); + break; + case NV_CTRL_BINARY_DATA_GPU_ECC_DETAILED_ERRORS_SINGLE_BIT_AGGREGATE: + ret = getDeviceMemoryCounts(ctrl_target, nvml, device, + NVML_MEMORY_ERROR_TYPE_CORRECTED, + NVML_AGGREGATE_ECC, + data, len); + break; + case NV_CTRL_BINARY_DATA_GPU_ECC_DETAILED_ERRORS_DOUBLE_BIT_AGGREGATE: + ret = getDeviceMemoryCounts(ctrl_target, nvml, device, + NVML_MEMORY_ERROR_TYPE_UNCORRECTED, + NVML_AGGREGATE_ECC, + data, len); + break; + case NV_CTRL_BINARY_DATA_FRAMELOCKS_USED_BY_GPU: case NV_CTRL_BINARY_DATA_THERMAL_SENSORS_USED_BY_GPU: case NV_CTRL_BINARY_DATA_DISPLAYS_CONNECTED_TO_GPU: case NV_CTRL_BINARY_DATA_DISPLAYS_ON_GPU: @@ -1356,7 +1620,7 @@ NvCtrlNvmlGetGPUBinaryAttribute(const CtrlTarget *ctrl_target, return NvCtrlNotSupported; } -#endif // NVML_EXPERIMENTAL + ReturnStatus NvCtrlNvmlGetBinaryAttribute(const CtrlTarget *ctrl_target, @@ -1366,7 +1630,6 @@ NvCtrlNvmlGetBinaryAttribute(const CtrlTarget *ctrl_target, return NvCtrlMissingExtension; } -#ifdef NVML_EXPERIMENTAL /* * This shouldn't be reached for target types that are not handled through * NVML (Keep TARGET_TYPE_IS_NVML_COMPATIBLE in NvCtrlAttributesPrivate.h up @@ -1398,10 +1661,6 @@ NvCtrlNvmlGetBinaryAttribute(const CtrlTarget *ctrl_target, default: return NvCtrlBadHandle; } - -#else - return NvCtrlNotSupported; -#endif } @@ -1410,28 +1669,31 @@ NvCtrlNvmlGetBinaryAttribute(const CtrlTarget *ctrl_target, * Get NVML Valid String Attribute Values */ -#ifdef NVML_EXPERIMENTAL + static ReturnStatus NvCtrlNvmlGetGPUValidStringAttributeValues(int attr, CtrlAttributeValidValues *val) { switch (attr) { + case NV_CTRL_STRING_NVIDIA_DRIVER_VERSION: case NV_CTRL_STRING_PRODUCT_NAME: case NV_CTRL_STRING_VBIOS_VERSION: - case NV_CTRL_STRING_NVIDIA_DRIVER_VERSION: + case NV_CTRL_STRING_GPU_UUID: + val->valid_type = CTRL_ATTRIBUTE_VALID_TYPE_STRING; + return NvCtrlSuccess; + case NV_CTRL_STRING_SLI_MODE: case NV_CTRL_STRING_PERFORMANCE_MODES: case NV_CTRL_STRING_MULTIGPU_MODE: case NV_CTRL_STRING_GPU_CURRENT_CLOCK_FREQS: - case NV_CTRL_STRING_GPU_UUID: case NV_CTRL_STRING_GPU_UTILIZATION: /* * XXX We'll eventually need to add support for this attributes. For * string attributes, NV-CONTROL only sets the attribute type * and permissions so no actual NVML call will be needed. */ - return NvCtrlNotSupported; + return NvCtrlAttributeNotAvailable; default: /* The attribute queried is not GPU-targeted */ @@ -1441,25 +1703,54 @@ NvCtrlNvmlGetGPUValidStringAttributeValues(int attr, return NvCtrlSuccess; } -#endif // NVML_EXPERIMENTAL + + +static ReturnStatus convertValidTypeToAttributeType(CtrlAttributeValidType val, + CtrlAttributeType *type) +{ + switch (val) { + case CTRL_ATTRIBUTE_VALID_TYPE_INTEGER: + case CTRL_ATTRIBUTE_VALID_TYPE_BOOL: + case CTRL_ATTRIBUTE_VALID_TYPE_BITMASK: + case CTRL_ATTRIBUTE_VALID_TYPE_64BIT_INTEGER: + *type = CTRL_ATTRIBUTE_TYPE_INTEGER; + break; + case CTRL_ATTRIBUTE_VALID_TYPE_STRING: + *type = CTRL_ATTRIBUTE_TYPE_STRING; + break; + case CTRL_ATTRIBUTE_VALID_TYPE_STRING_OPERATION: + *type = CTRL_ATTRIBUTE_TYPE_STRING_OPERATION; + break; + case CTRL_ATTRIBUTE_VALID_TYPE_BINARY_DATA: + *type = CTRL_ATTRIBUTE_TYPE_BINARY_DATA; + break; + default: + return NvCtrlAttributeNotAvailable; + } + + return NvCtrlSuccess; +} + + ReturnStatus NvCtrlNvmlGetValidStringAttributeValues(const CtrlTarget *ctrl_target, int attr, CtrlAttributeValidValues *val) { + const NvCtrlAttributePrivateHandle *h = getPrivateHandleConst(ctrl_target); + ReturnStatus ret = NvCtrlAttributeNotAvailable; + CtrlAttributeType attr_type; + if (NvmlMissing(ctrl_target)) { return NvCtrlMissingExtension; } -#ifdef NVML_EXPERIMENTAL - ReturnStatus ret; - /* - * This shouldn't be reached for target types that are not handled through - * NVML (Keep TARGET_TYPE_IS_NVML_COMPATIBLE in NvCtrlAttributesPrivate.h up - * to date). - */ - assert(TARGET_TYPE_IS_NVML_COMPATIBLE(NvCtrlGetTargetType(ctrl_target))); + if (val) { + memset(val, 0, sizeof(*val)); + } else { + return NvCtrlBadArgument; + } switch (NvCtrlGetTargetType(ctrl_target)) { case GPU_TARGET: @@ -1477,31 +1768,17 @@ NvCtrlNvmlGetValidStringAttributeValues(const CtrlTarget *ctrl_target, break; } - - /* - * XXX Did we forgot to handle this attribute? - REMOVE THIS after - * nvidia-settings NVML migration work is done - */ - if (ret == NvCtrlAttributeNotAvailable) { - const NvCtrlAttributePrivateHandle *h = getPrivateHandleConst(ctrl_target); - ReturnStatus ret2; - - if (!h->nv) { - return NvCtrlMissingExtension; - } - - ret2 = NvCtrlNvControlGetValidStringDisplayAttributeValues(h, 0, attr, val); + if (ret == NvCtrlSuccess) { + val->valid_type = CTRL_ATTRIBUTE_VALID_TYPE_STRING; + } - assert(ret2 == NvCtrlAttributeNotAvailable); + ret = convertValidTypeToAttributeType(val->valid_type, &attr_type); - return ret2; + if (ret != NvCtrlSuccess) { + return ret; } - return ret; - -#else - return NvCtrlNotSupported; -#endif + return NvCtrlNvmlGetAttributePerms(h, attr_type, attr, &val->permissions); } @@ -1510,7 +1787,7 @@ NvCtrlNvmlGetValidStringAttributeValues(const CtrlTarget *ctrl_target, * Get NVML Valid Attribute Values */ -#ifdef NVML_EXPERIMENTAL + static ReturnStatus NvCtrlNvmlGetGPUValidAttributeValues(const CtrlTarget *ctrl_target, int attr, @@ -1527,10 +1804,11 @@ NvCtrlNvmlGetGPUValidAttributeValues(const CtrlTarget *ctrl_target, int attr, nvml = h->nvml; + val->permissions.write = NV_FALSE; + ret = nvml->lib.deviceGetHandleByIndex(nvml->deviceIdx, &device); if (ret == NVML_SUCCESS) { switch (attr) { - case NV_CTRL_VIDEO_RAM: case NV_CTRL_TOTAL_DEDICATED_GPU_MEMORY: case NV_CTRL_USED_DEDICATED_GPU_MEMORY: case NV_CTRL_PCI_DOMAIN: @@ -1539,27 +1817,46 @@ NvCtrlNvmlGetGPUValidAttributeValues(const CtrlTarget *ctrl_target, int attr, case NV_CTRL_PCI_FUNCTION: case NV_CTRL_PCI_ID: case NV_CTRL_GPU_PCIE_GENERATION: - case NV_CTRL_GPU_PCIE_MAX_LINK_WIDTH: case NV_CTRL_GPU_PCIE_CURRENT_LINK_WIDTH: - case NV_CTRL_GPU_PCIE_MAX_LINK_SPEED: - case NV_CTRL_GPU_PCIE_CURRENT_LINK_SPEED: - case NV_CTRL_BUS_TYPE: + case NV_CTRL_GPU_PCIE_MAX_LINK_WIDTH: + case NV_CTRL_GPU_SLOWDOWN_THRESHOLD: + case NV_CTRL_GPU_SHUTDOWN_THRESHOLD: + case NV_CTRL_GPU_CORE_TEMPERATURE: case NV_CTRL_GPU_MEMORY_BUS_WIDTH: case NV_CTRL_GPU_CORES: case NV_CTRL_IRQ: - case NV_CTRL_GPU_COOLER_MANUAL_CONTROL: case NV_CTRL_GPU_POWER_SOURCE: - case NV_CTRL_GPU_CURRENT_PERFORMANCE_LEVEL: - case NV_CTRL_GPU_ADAPTIVE_CLOCK_STATE: - case NV_CTRL_GPU_POWER_MIZER_MODE: - case NV_CTRL_GPU_POWER_MIZER_DEFAULT_MODE: + val->valid_type = CTRL_ATTRIBUTE_VALID_TYPE_INTEGER; + break; + case NV_CTRL_GPU_ECC_SUPPORTED: case NV_CTRL_GPU_ECC_STATUS: case NV_CTRL_GPU_ECC_CONFIGURATION: - case NV_CTRL_GPU_ECC_DEFAULT_CONFIGURATION: + case NV_CTRL_GPU_ECC_CONFIGURATION_SUPPORTED: + val->valid_type = CTRL_ATTRIBUTE_VALID_TYPE_BOOL; + break; + + case NV_CTRL_GPU_ECC_SINGLE_BIT_ERRORS: + case NV_CTRL_GPU_ECC_AGGREGATE_SINGLE_BIT_ERRORS: case NV_CTRL_GPU_ECC_DOUBLE_BIT_ERRORS: case NV_CTRL_GPU_ECC_AGGREGATE_DOUBLE_BIT_ERRORS: - case NV_CTRL_GPU_ECC_CONFIGURATION_SUPPORTED: + val->valid_type = CTRL_ATTRIBUTE_VALID_TYPE_64BIT_INTEGER; + break; + + case NV_CTRL_GPU_ECC_RESET_ERROR_STATUS: + val->valid_type = CTRL_ATTRIBUTE_VALID_TYPE_BITMASK; + break; + + case NV_CTRL_GPU_ECC_DEFAULT_CONFIGURATION: + case NV_CTRL_VIDEO_RAM: + case NV_CTRL_GPU_PCIE_MAX_LINK_SPEED: + case NV_CTRL_GPU_PCIE_CURRENT_LINK_SPEED: + case NV_CTRL_BUS_TYPE: + case NV_CTRL_GPU_COOLER_MANUAL_CONTROL: + case NV_CTRL_GPU_CURRENT_PERFORMANCE_LEVEL: + case NV_CTRL_GPU_ADAPTIVE_CLOCK_STATE: + case NV_CTRL_GPU_POWER_MIZER_MODE: + case NV_CTRL_GPU_POWER_MIZER_DEFAULT_MODE: case NV_CTRL_ENABLED_DISPLAYS: case NV_CTRL_CONNECTED_DISPLAYS: case NV_CTRL_MAX_SCREEN_WIDTH: @@ -1574,10 +1871,8 @@ NvCtrlNvmlGetGPUValidAttributeValues(const CtrlTarget *ctrl_target, int attr, case NV_CTRL_ATTR_NV_MINOR_VERSION: case NV_CTRL_OPERATING_SYSTEM: case NV_CTRL_NO_SCANOUT: - case NV_CTRL_GPU_CORE_TEMPERATURE: case NV_CTRL_AMBIENT_TEMPERATURE: case NV_CTRL_GPU_CURRENT_CLOCK_FREQS: - case NV_CTRL_GPU_CURRENT_PROCESSOR_CLOCK_FREQS: case NV_CTRL_VIDEO_ENCODER_UTILIZATION: case NV_CTRL_VIDEO_DECODER_UTILIZATION: case NV_CTRL_FRAMELOCK: @@ -1599,7 +1894,7 @@ NvCtrlNvmlGetGPUValidAttributeValues(const CtrlTarget *ctrl_target, int attr, * XXX We'll eventually need to add support for this attributes * through NVML */ - return NvCtrlNotSupported; + return NvCtrlAttributeNotAvailable; default: /* The attribute queried is not GPU-targeted */ @@ -1613,7 +1908,7 @@ NvCtrlNvmlGetGPUValidAttributeValues(const CtrlTarget *ctrl_target, int attr, /* An NVML error occurred */ printNvmlError(ret); - return NvCtrlNotSupported; + return NvCtrlNoAttribute; } static ReturnStatus @@ -1651,7 +1946,7 @@ NvCtrlNvmlGetThermalValidAttributeValues(const CtrlTarget *ctrl_target, * XXX We'll eventually need to add support for this attributes * through NVML */ - return NvCtrlNotSupported; + return NvCtrlAttributeNotAvailable; default: /* The attribute queried is not sensor-targeted */ @@ -1665,7 +1960,7 @@ NvCtrlNvmlGetThermalValidAttributeValues(const CtrlTarget *ctrl_target, /* An NVML error occurred */ printNvmlError(ret); - return NvCtrlNotSupported; + return NvCtrlNoAttribute; } static ReturnStatus @@ -1696,6 +1991,13 @@ NvCtrlNvmlGetCoolerValidAttributeValues(const CtrlTarget *ctrl_target, ret = nvml->lib.deviceGetHandleByIndex(nvml->deviceIdx, &device); if (ret == NVML_SUCCESS) { switch (attr) { + case NV_CTRL_THERMAL_COOLER_CURRENT_LEVEL: + /* Range as a percent */ + val->valid_type = CTRL_ATTRIBUTE_VALID_TYPE_RANGE; + val->range.min = 0; + val->range.max = 100; + return NvCtrlSuccess; + case NV_CTRL_THERMAL_COOLER_LEVEL: case NV_CTRL_THERMAL_COOLER_SPEED: case NV_CTRL_THERMAL_COOLER_CONTROL_TYPE: @@ -1704,7 +2006,7 @@ NvCtrlNvmlGetCoolerValidAttributeValues(const CtrlTarget *ctrl_target, * XXX We'll eventually need to add support for this attributes * through NVML */ - return NvCtrlNotSupported; + return NvCtrlAttributeNotAvailable; default: /* The attribute queried is not fan-targeted */ @@ -1718,22 +2020,24 @@ NvCtrlNvmlGetCoolerValidAttributeValues(const CtrlTarget *ctrl_target, /* An NVML error occurred */ printNvmlError(ret); - return NvCtrlNotSupported; + return NvCtrlNoAttribute; } -#endif // NVML_EXPERIMENTAL + ReturnStatus NvCtrlNvmlGetValidAttributeValues(const CtrlTarget *ctrl_target, int attr, CtrlAttributeValidValues *val) { + const NvCtrlAttributePrivateHandle *h = getPrivateHandleConst(ctrl_target); + ReturnStatus ret = NvCtrlAttributeNotAvailable; + CtrlAttributeType attr_type; + if (NvmlMissing(ctrl_target)) { return NvCtrlMissingExtension; } -#ifdef NVML_EXPERIMENTAL - ReturnStatus ret; /* * This shouldn't be reached for target types that are not handled through * NVML (Keep TARGET_TYPE_IS_NVML_COMPATIBLE in NvCtrlAttributesPrivate.h up @@ -1764,30 +2068,136 @@ NvCtrlNvmlGetValidAttributeValues(const CtrlTarget *ctrl_target, ret = NvCtrlBadHandle; } - - /* - * XXX Did we forgot to handle this attribute? - REMOVE THIS after - * nvidia-settings NVML migration work is done - */ - if (ret == NvCtrlAttributeNotAvailable) { - const NvCtrlAttributePrivateHandle *h = getPrivateHandleConst(ctrl_target); - ReturnStatus ret2; + if (ret != NvCtrlSuccess) { + return ret; + } - if (!h->nv) { - return NvCtrlMissingExtension; - } + ret = convertValidTypeToAttributeType(val->valid_type, &attr_type); + + if (ret != NvCtrlSuccess) { + return ret; + } + + return NvCtrlNvmlGetAttributePerms(h, attr_type, attr, &val->permissions); +} + +static ReturnStatus NvCtrlNvmlGetIntegerAttributePerms(int attr, + CtrlAttributePerms *perms) +{ + /* Set write permissions */ + switch (attr) { + case NV_CTRL_GPU_ECC_CONFIGURATION: + case NV_CTRL_GPU_ECC_RESET_ERROR_STATUS: + perms->write = NV_TRUE; + break; + default: + perms->write = NV_FALSE; + } + + /* Valid target and read permissions */ + switch (attr) { + case NV_CTRL_TOTAL_DEDICATED_GPU_MEMORY: + case NV_CTRL_USED_DEDICATED_GPU_MEMORY: + case NV_CTRL_PCI_DOMAIN: + case NV_CTRL_PCI_BUS: + case NV_CTRL_PCI_DEVICE: + case NV_CTRL_PCI_FUNCTION: + case NV_CTRL_PCI_ID: + case NV_CTRL_GPU_PCIE_GENERATION: + case NV_CTRL_GPU_PCIE_CURRENT_LINK_WIDTH: + case NV_CTRL_GPU_PCIE_MAX_LINK_WIDTH: + case NV_CTRL_GPU_SLOWDOWN_THRESHOLD: + case NV_CTRL_GPU_SHUTDOWN_THRESHOLD: + case NV_CTRL_GPU_CORE_TEMPERATURE: + case NV_CTRL_GPU_MEMORY_BUS_WIDTH: + case NV_CTRL_GPU_CORES: + case NV_CTRL_IRQ: + case NV_CTRL_GPU_POWER_SOURCE: + /* CTRL_ATTRIBUTE_VALID_TYPE_BOOL */ + case NV_CTRL_GPU_ECC_SUPPORTED: + case NV_CTRL_GPU_ECC_CONFIGURATION_SUPPORTED: + case NV_CTRL_GPU_ECC_STATUS: + case NV_CTRL_GPU_ECC_CONFIGURATION: + /* CTRL_ATTRIBUTE_VALID_TYPE_64BIT_INTEGER */ + case NV_CTRL_GPU_ECC_SINGLE_BIT_ERRORS: + case NV_CTRL_GPU_ECC_AGGREGATE_SINGLE_BIT_ERRORS: + case NV_CTRL_GPU_ECC_DOUBLE_BIT_ERRORS: + case NV_CTRL_GPU_ECC_AGGREGATE_DOUBLE_BIT_ERRORS: + perms->read = NV_TRUE; + perms->valid_targets = CTRL_TARGET_PERM_BIT(GPU_TARGET); + break; - ret2 = NvCtrlNvControlGetValidAttributeValues(h, 0, attr, val); + /* GPU_TARGET non-readable attribute */ + case NV_CTRL_GPU_ECC_RESET_ERROR_STATUS: + perms->read = NV_FALSE; + perms->valid_targets = CTRL_TARGET_PERM_BIT(GPU_TARGET); + break; - assert(ret2 == NvCtrlAttributeNotAvailable); + case NV_CTRL_THERMAL_COOLER_CURRENT_LEVEL: + perms->valid_targets = CTRL_TARGET_PERM_BIT(COOLER_TARGET); + perms->read = NV_TRUE; + break; - return ret2; + default: + perms->valid_targets = 0; + perms->read = NV_FALSE; + return NvCtrlNotSupported; + } + + return NvCtrlSuccess; +} + +static ReturnStatus NvCtrlNvmlGetStringAttributePerms(int attr, + CtrlAttributePerms *perms) +{ + perms->write = NV_FALSE; + + switch (attr) { + case NV_CTRL_STRING_NVIDIA_DRIVER_VERSION: + case NV_CTRL_STRING_PRODUCT_NAME: + case NV_CTRL_STRING_VBIOS_VERSION: + case NV_CTRL_STRING_GPU_UUID: + perms->valid_targets = CTRL_TARGET_PERM_BIT(GPU_TARGET); + perms->read = NV_TRUE; + break; + default: + perms->valid_targets = 0; + perms->read = NV_FALSE; + return NvCtrlNotSupported; + } + return NvCtrlSuccess; +} + + +ReturnStatus +NvCtrlNvmlGetAttributePerms(const NvCtrlAttributePrivateHandle *h, + CtrlAttributeType attr_type, int attr, + CtrlAttributePerms *perms) +{ + ReturnStatus ret = NvCtrlSuccess; + + if (!h->nvml) { + return NvCtrlBadArgument; + } + + switch (attr_type) { + case CTRL_ATTRIBUTE_TYPE_INTEGER: + ret = NvCtrlNvmlGetIntegerAttributePerms(attr, perms); + break; + + case CTRL_ATTRIBUTE_TYPE_STRING: + ret = NvCtrlNvmlGetStringAttributePerms(attr, perms); + break; + + case CTRL_ATTRIBUTE_TYPE_BINARY_DATA: + return NvCtrlBadArgument; + break; + + default: + return NvCtrlBadArgument; } return ret; -#else - return NvCtrlNotSupported; -#endif } |