From dfb061cbdbc0a87391e475b5d86303cb028eb549 Mon Sep 17 00:00:00 2001 From: Thomas Fleury Date: Fri, 21 Oct 2016 16:43:47 -0700 Subject: gpu: nvgpu: get voltage, current, power and temperature Add ioctls to retrieve voltage, current, power and temperature. Add flags in GPU characteristics to indicate if feature is supported. Jira DNVGPU-166 Change-Id: Idd5a767326c9d43630e8289ca7d2c27bb96a9f14 Signed-off-by: David Nieto Reviewed-on: http://git-master/r/1241862 Tested-by: Thomas Fleury GVS: Gerrit_Virtual_Submit Reviewed-by: Terje Bergstrom Reviewed-by: Vijayakumar Subbu Reviewed-on: http://git-master/r/1267153 --- drivers/gpu/nvgpu/gk20a/ctrl_gk20a.c | 134 ++++++++++++++++++++++++++++++++++- drivers/gpu/nvgpu/gk20a/gk20a.h | 1 + include/uapi/linux/nvgpu.h | 33 +++++++++ 3 files changed, 167 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/nvgpu/gk20a/ctrl_gk20a.c b/drivers/gpu/nvgpu/gk20a/ctrl_gk20a.c index 3de84851..23fbdce0 100644 --- a/drivers/gpu/nvgpu/gk20a/ctrl_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/ctrl_gk20a.c @@ -1063,7 +1063,6 @@ static int nvgpu_gpu_clk_set_info(struct gk20a *g, return ret; } - static int nvgpu_gpu_clk_get_info(struct gk20a *g, struct gk20a_ctrl_priv *priv, struct nvgpu_gpu_clk_get_info_args *args) @@ -1172,6 +1171,119 @@ static int nvgpu_gpu_clk_get_event_fd(struct gk20a *g, return nvgpu_clk_arb_install_event_fd(g, session, &args->event_fd); } + +static int nvgpu_gpu_get_voltage(struct gk20a *g, + struct nvgpu_gpu_get_voltage_args *args) +{ + int err = -EINVAL; + + gk20a_dbg_fn(""); + + if (args->reserved) + return -EINVAL; + + if (!(g->gpu_characteristics.flags & NVGPU_GPU_FLAGS_SUPPORT_GET_VOLTAGE)) + return -EINVAL; + + err = gk20a_busy(g->dev); + if (err) + return err; + + switch (args->which) { + case NVGPU_GPU_VOLTAGE_CORE: + err = volt_get_voltage(g, CTRL_VOLT_DOMAIN_LOGIC, &args->voltage); + break; + case NVGPU_GPU_VOLTAGE_SRAM: + err = volt_get_voltage(g, CTRL_VOLT_DOMAIN_SRAM, &args->voltage); + break; + case NVGPU_GPU_VOLTAGE_BUS: + err = pmgr_pwr_devices_get_voltage(g, &args->voltage); + break; + default: + err = -EINVAL; + } + + gk20a_idle(g->dev); + + return err; +} + +static int nvgpu_gpu_get_current(struct gk20a *g, + struct nvgpu_gpu_get_current_args *args) +{ + int err; + + gk20a_dbg_fn(""); + + if (args->reserved[0] || args->reserved[1] || args->reserved[2]) + return -EINVAL; + + if (!(g->gpu_characteristics.flags & NVGPU_GPU_FLAGS_SUPPORT_GET_CURRENT)) + return -EINVAL; + + err = gk20a_busy(g->dev); + if (err) + return err; + + err = pmgr_pwr_devices_get_current(g, &args->currnt); + + gk20a_idle(g->dev); + + return err; +} + +static int nvgpu_gpu_get_power(struct gk20a *g, + struct nvgpu_gpu_get_power_args *args) +{ + int err; + + gk20a_dbg_fn(""); + + if (args->reserved[0] || args->reserved[1] || args->reserved[2]) + return -EINVAL; + + if (!(g->gpu_characteristics.flags & NVGPU_GPU_FLAGS_SUPPORT_GET_POWER)) + return -EINVAL; + + err = gk20a_busy(g->dev); + if (err) + return err; + + err = pmgr_pwr_devices_get_power(g, &args->power); + + gk20a_idle(g->dev); + + return err; +} + +static int nvgpu_gpu_get_temperature(struct gk20a *g, + struct nvgpu_gpu_get_temperature_args *args) +{ + int err; + u32 temp_f24_8; + + gk20a_dbg_fn(""); + + if (args->reserved[0] || args->reserved[1] || args->reserved[2]) + return -EINVAL; + + if (!g->ops.therm.get_internal_sensor_curr_temp) + return -EINVAL; + + err = gk20a_busy(g->dev); + if (err) + return err; + + err = g->ops.therm.get_internal_sensor_curr_temp(g, &temp_f24_8); + + gk20a_idle(g->dev); + + /* Convert from standard S24.8 fixed point to mC */ + if (!err) + args->temperature = (temp_f24_8 * 1000) / 256; + + return err; +} #endif long gk20a_ctrl_dev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) @@ -1461,6 +1573,26 @@ long gk20a_ctrl_dev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg err = nvgpu_gpu_clk_get_event_fd(g, priv, (struct nvgpu_gpu_clk_get_event_fd_args *)buf); break; + + case NVGPU_GPU_IOCTL_GET_VOLTAGE: + err = nvgpu_gpu_get_voltage(g, + (struct nvgpu_gpu_get_voltage_args *)buf); + break; + + case NVGPU_GPU_IOCTL_GET_CURRENT: + err = nvgpu_gpu_get_current(g, + (struct nvgpu_gpu_get_current_args *)buf); + break; + + case NVGPU_GPU_IOCTL_GET_POWER: + err = nvgpu_gpu_get_power(g, + (struct nvgpu_gpu_get_power_args *)buf); + break; + + case NVGPU_GPU_IOCTL_GET_TEMPERATURE: + err = nvgpu_gpu_get_temperature(g, + (struct nvgpu_gpu_get_temperature_args *)buf); + break; #endif default: diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.h b/drivers/gpu/nvgpu/gk20a/gk20a.h index 564026a4..071111ab 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/gk20a.h @@ -588,6 +588,7 @@ struct gpu_ops { int (*init_therm_setup_hw)(struct gk20a *g); int (*elcg_init_idle_filters)(struct gk20a *g); void (*therm_debugfs_init)(struct gk20a *g); + int (*get_internal_sensor_curr_temp)(struct gk20a *g, u32 *temp_f24_8); } therm; struct { bool (*is_pmu_supported)(struct gk20a *g); diff --git a/include/uapi/linux/nvgpu.h b/include/uapi/linux/nvgpu.h index 13492e0d..f45be911 100644 --- a/include/uapi/linux/nvgpu.h +++ b/include/uapi/linux/nvgpu.h @@ -721,6 +721,31 @@ struct nvgpu_gpu_get_fbp_l2_masks_args { __u64 mask_buf_addr; }; +#define NVGPU_GPU_VOLTAGE_CORE 1 +#define NVGPU_GPU_VOLTAGE_SRAM 2 +#define NVGPU_GPU_VOLTAGE_BUS 3 /* input to regulator */ + +struct nvgpu_gpu_get_voltage_args { + __u64 reserved; + __u32 which; /* in: NVGPU_GPU_VOLTAGE_* */ + __u32 voltage; /* uV */ +}; + +struct nvgpu_gpu_get_current_args { + __u32 reserved[3]; + __u32 currnt; /* mA */ +}; + +struct nvgpu_gpu_get_power_args { + __u32 reserved[3]; + __u32 power; /* mW */ +}; + +struct nvgpu_gpu_get_temperature_args { + __u32 reserved[3]; + __u32 temperature; /* mC */ +}; + #define NVGPU_GPU_IOCTL_ZCULL_GET_CTX_SIZE \ _IOR(NVGPU_GPU_IOCTL_MAGIC, 1, struct nvgpu_gpu_zcull_get_ctx_size_args) #define NVGPU_GPU_IOCTL_ZCULL_GET_INFO \ @@ -792,6 +817,14 @@ struct nvgpu_gpu_get_fbp_l2_masks_args { #define NVGPU_GPU_IOCTL_GET_MEMORY_STATE \ _IOWR(NVGPU_GPU_IOCTL_MAGIC, 33, \ struct nvgpu_gpu_get_memory_state_args) +#define NVGPU_GPU_IOCTL_GET_VOLTAGE \ + _IOWR(NVGPU_GPU_IOCTL_MAGIC, 33, struct nvgpu_gpu_get_voltage_args) +#define NVGPU_GPU_IOCTL_GET_CURRENT \ + _IOWR(NVGPU_GPU_IOCTL_MAGIC, 34, struct nvgpu_gpu_get_current_args) +#define NVGPU_GPU_IOCTL_GET_POWER \ + _IOWR(NVGPU_GPU_IOCTL_MAGIC, 35, struct nvgpu_gpu_get_power_args) +#define NVGPU_GPU_IOCTL_GET_TEMPERATURE \ + _IOWR(NVGPU_GPU_IOCTL_MAGIC, 36, struct nvgpu_gpu_get_temperature_args) #define NVGPU_GPU_IOCTL_GET_FBP_L2_MASKS \ _IOWR(NVGPU_GPU_IOCTL_MAGIC, 38, struct nvgpu_gpu_get_fbp_l2_masks_args) #define NVGPU_GPU_IOCTL_LAST \ -- cgit v1.2.2