Created
December 18, 2017 11:02
-
-
Save wethu/fa91bc2bb295e2807e4778d67c55a0a4 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/sys/dev/drm2/radeon/radeon.h b/sys/dev/drm2/radeon/radeon.h | |
index 4a63cf647332b..3063fa728feca 100644 | |
--- a/sys/dev/drm2/radeon/radeon.h | |
+++ b/sys/dev/drm2/radeon/radeon.h | |
@@ -203,6 +203,8 @@ void radeon_pm_fini(struct radeon_device *rdev); | |
void radeon_pm_compute_clocks(struct radeon_device *rdev); | |
void radeon_pm_suspend(struct radeon_device *rdev); | |
void radeon_pm_resume(struct radeon_device *rdev); | |
+extern int radeon_pm_sysctl_init(struct drm_device *dev, | |
+ struct sysctl_ctx_list *ctx, struct sysctl_oid *top); | |
void radeon_combios_get_power_modes(struct radeon_device *rdev); | |
void radeon_atombios_get_power_modes(struct radeon_device *rdev); | |
void radeon_atom_set_voltage(struct radeon_device *rdev, u16 voltage_level, u8 voltage_type); | |
diff --git a/sys/dev/drm2/radeon/radeon_drv.c b/sys/dev/drm2/radeon/radeon_drv.c | |
index 39506319c026b..74c3c646119f4 100644 | |
--- a/sys/dev/drm2/radeon/radeon_drv.c | |
+++ b/sys/dev/drm2/radeon/radeon_drv.c | |
@@ -85,6 +85,8 @@ extern int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, | |
int *vpos, int *hpos); | |
extern struct drm_ioctl_desc radeon_ioctls_kms[]; | |
extern int radeon_max_kms_ioctl; | |
+extern int radeon_pm_sysctl_init(struct drm_device *dev, | |
+ struct sysctl_ctx_list *ctx, struct sysctl_oid *top); | |
#ifdef FREEBSD_WIP | |
int radeon_mmap(struct file *filp, struct vm_area_struct *vma); | |
#endif /* FREEBSD_WIP */ | |
@@ -203,6 +205,7 @@ static struct drm_driver kms_driver; | |
static int radeon_sysctl_init(struct drm_device *dev, struct sysctl_ctx_list *ctx, | |
struct sysctl_oid *top) | |
{ | |
+ radeon_pm_sysctl_init(dev, ctx, top); | |
return drm_add_busid_modesetting(dev, ctx, top); | |
} | |
diff --git a/sys/dev/drm2/radeon/radeon_pm.c b/sys/dev/drm2/radeon/radeon_pm.c | |
index 18d800334be4f..5c0626403324e 100644 | |
--- a/sys/dev/drm2/radeon/radeon_pm.c | |
+++ b/sys/dev/drm2/radeon/radeon_pm.c | |
@@ -336,36 +336,31 @@ static void radeon_pm_print_states(struct radeon_device *rdev) | |
} | |
} | |
-#ifdef FREEBSD_WIP | |
-static ssize_t radeon_get_pm_profile(struct device *dev, | |
- struct device_attribute *attr, | |
+static int radeon_get_pm_profile(struct radeon_device *rdev, | |
char *buf) | |
{ | |
- struct drm_device *ddev = pci_get_drvdata(to_pci_dev(dev)); | |
- struct radeon_device *rdev = ddev->dev_private; | |
int cp = rdev->pm.profile; | |
- return snprintf(buf, PAGE_SIZE, "%s\n", | |
+ return snprintf(buf, 32, "%s", | |
(cp == PM_PROFILE_AUTO) ? "auto" : | |
(cp == PM_PROFILE_LOW) ? "low" : | |
(cp == PM_PROFILE_MID) ? "mid" : | |
(cp == PM_PROFILE_HIGH) ? "high" : "default"); | |
} | |
-static ssize_t radeon_set_pm_profile(struct device *dev, | |
- struct device_attribute *attr, | |
- const char *buf, | |
- size_t count) | |
+static int radeon_set_pm_profile(struct radeon_device *rdev, | |
+ const char *buf) | |
{ | |
- struct drm_device *ddev = pci_get_drvdata(to_pci_dev(dev)); | |
- struct radeon_device *rdev = ddev->dev_private; | |
+ int error = 0; | |
sx_xlock(&rdev->pm.mutex); | |
if (rdev->pm.pm_method == PM_METHOD_PROFILE) { | |
if (strncmp("default", buf, strlen("default")) == 0) | |
rdev->pm.profile = PM_PROFILE_DEFAULT; | |
+#ifdef FREEBSD_WIP | |
else if (strncmp("auto", buf, strlen("auto")) == 0) | |
rdev->pm.profile = PM_PROFILE_AUTO; | |
+#endif /* FREEBSD_WIP */ | |
else if (strncmp("low", buf, strlen("low")) == 0) | |
rdev->pm.profile = PM_PROFILE_LOW; | |
else if (strncmp("mid", buf, strlen("mid")) == 0) | |
@@ -373,48 +368,44 @@ static ssize_t radeon_set_pm_profile(struct device *dev, | |
else if (strncmp("high", buf, strlen("high")) == 0) | |
rdev->pm.profile = PM_PROFILE_HIGH; | |
else { | |
- count = -EINVAL; | |
+ error = -EINVAL; | |
goto fail; | |
} | |
radeon_pm_update_profile(rdev); | |
radeon_pm_set_clocks(rdev); | |
} else | |
- count = -EINVAL; | |
+ error = -EINVAL; | |
fail: | |
sx_xunlock(&rdev->pm.mutex); | |
- return count; | |
+ return error; | |
} | |
-static ssize_t radeon_get_pm_method(struct device *dev, | |
- struct device_attribute *attr, | |
+static int radeon_get_pm_method(struct radeon_device *rdev, | |
char *buf) | |
{ | |
- struct drm_device *ddev = pci_get_drvdata(to_pci_dev(dev)); | |
- struct radeon_device *rdev = ddev->dev_private; | |
int pm = rdev->pm.pm_method; | |
- return snprintf(buf, PAGE_SIZE, "%s\n", | |
+ return snprintf(buf, 32, "%s\n", | |
(pm == PM_METHOD_DYNPM) ? "dynpm" : "profile"); | |
} | |
-static ssize_t radeon_set_pm_method(struct device *dev, | |
- struct device_attribute *attr, | |
- const char *buf, | |
- size_t count) | |
+static int radeon_set_pm_method(struct radeon_device *rdev, | |
+ const char *buf) | |
{ | |
- struct drm_device *ddev = pci_get_drvdata(to_pci_dev(dev)); | |
- struct radeon_device *rdev = ddev->dev_private; | |
- | |
+ int error = 0; | |
+#ifdef FREEBSD_WIP | |
if (strncmp("dynpm", buf, strlen("dynpm")) == 0) { | |
sx_xlock(&rdev->pm.mutex); | |
rdev->pm.pm_method = PM_METHOD_DYNPM; | |
rdev->pm.dynpm_state = DYNPM_STATE_PAUSED; | |
rdev->pm.dynpm_planned_action = DYNPM_ACTION_DEFAULT; | |
sx_xunlock(&rdev->pm.mutex); | |
- } else if (strncmp("profile", buf, strlen("profile")) == 0) { | |
+ } else | |
+#endif /* FREEBSD_WIP */ | |
+ if (strncmp("profile", buf, strlen("profile")) == 0) { | |
sx_xlock(&rdev->pm.mutex); | |
/* disable dynpm */ | |
rdev->pm.dynpm_state = DYNPM_STATE_DISABLED; | |
@@ -425,17 +416,57 @@ static ssize_t radeon_set_pm_method(struct device *dev, | |
cancel_delayed_work_sync(&rdev->pm.dynpm_idle_work); | |
#endif /* FREEBSD_WIP */ | |
} else { | |
- count = -EINVAL; | |
+ error = -EINVAL; | |
goto fail; | |
} | |
radeon_pm_compute_clocks(rdev); | |
fail: | |
- return count; | |
+ return error; | |
} | |
-static DEVICE_ATTR(power_profile, S_IRUGO | S_IWUSR, radeon_get_pm_profile, radeon_set_pm_profile); | |
-static DEVICE_ATTR(power_method, S_IRUGO | S_IWUSR, radeon_get_pm_method, radeon_set_pm_method); | |
+static int | |
+power_profile_handler(SYSCTL_HANDLER_ARGS) | |
+{ | |
+ char newname[32]; | |
+ struct drm_device *dev; | |
+ struct radeon_device *rdev; | |
+ int error; | |
+ | |
+ dev = arg1; | |
+ rdev = dev->dev_private; | |
+ if (rdev == NULL) | |
+ return (EBUSY); | |
+ | |
+ radeon_get_pm_profile(rdev, newname); | |
+ error = sysctl_handle_string(oidp, newname, sizeof(newname), req); | |
+ if (error != 0 || req->newptr == NULL) | |
+ return (error); | |
+ error = radeon_set_pm_profile(rdev, newname); | |
+ return (-error); | |
+} | |
+ | |
+static int | |
+power_method_handler(SYSCTL_HANDLER_ARGS) | |
+{ | |
+ char newname[32]; | |
+ struct drm_device *dev; | |
+ struct radeon_device *rdev; | |
+ int error; | |
+ | |
+ dev = arg1; | |
+ rdev = dev->dev_private; | |
+ if (rdev == NULL) | |
+ return (EBUSY); | |
+ | |
+ radeon_get_pm_method(rdev, newname); | |
+ error = sysctl_handle_string(oidp, newname, sizeof(newname), req); | |
+ if (error != 0 || req->newptr == NULL) | |
+ return (error); | |
+ error = radeon_set_pm_method(rdev, newname); | |
+ return (-error); | |
+} | |
+#ifdef FREEBSD_WIP | |
static ssize_t radeon_hwmon_show_temp(struct device *dev, | |
struct device_attribute *attr, | |
char *buf) | |
@@ -648,14 +679,14 @@ int radeon_pm_init(struct radeon_device *rdev) | |
/* where's the best place to put these? */ | |
#ifdef FREEBSD_WIP | |
ret = device_create_file(rdev->dev, &dev_attr_power_profile); | |
-#endif /* FREEBSD_WIP */ | |
if (ret) | |
DRM_ERROR("failed to create device file for power profile\n"); | |
+#endif /* FREEBSD_WIP */ | |
#ifdef FREEBSD_WIP | |
ret = device_create_file(rdev->dev, &dev_attr_power_method); | |
-#endif /* FREEBSD_WIP */ | |
if (ret) | |
DRM_ERROR("failed to create device file for power method\n"); | |
+#endif /* FREEBSD_WIP */ | |
if (radeon_debugfs_pm_init(rdev)) { | |
DRM_ERROR("Failed to register debugfs file for PM!\n"); | |
@@ -918,3 +949,107 @@ static int radeon_debugfs_pm_init(struct radeon_device *rdev) | |
return 0; | |
#endif | |
} | |
+ | |
+static int | |
+radeon_temp_handler(SYSCTL_HANDLER_ARGS) | |
+{ | |
+ struct drm_device *dev; | |
+ struct radeon_device *rdev; | |
+ int error; | |
+ int temp; | |
+ | |
+ dev = arg1; | |
+ rdev = dev->dev_private; | |
+ if (rdev == NULL) | |
+ return (EBUSY); | |
+ | |
+ switch (rdev->pm.int_thermal_type) { | |
+ case THERMAL_TYPE_RV6XX: | |
+ temp = rv6xx_get_temp(rdev); | |
+ break; | |
+ case THERMAL_TYPE_RV770: | |
+ temp = rv770_get_temp(rdev); | |
+ break; | |
+ case THERMAL_TYPE_EVERGREEN: | |
+ case THERMAL_TYPE_NI: | |
+ temp = evergreen_get_temp(rdev); | |
+ break; | |
+ case THERMAL_TYPE_SUMO: | |
+ temp = sumo_get_temp(rdev); | |
+ break; | |
+ case THERMAL_TYPE_SI: | |
+ temp = si_get_temp(rdev); | |
+ break; | |
+ default: | |
+ temp = 0; | |
+ break; | |
+ } | |
+ | |
+ /* Convert from millidegrees Celsius to decidegrees Kelvin. */ | |
+ temp = temp / 100 + 2732; | |
+ error = sysctl_handle_int(oidp, &temp, 0, req); | |
+ return (error); | |
+} | |
+ | |
+static int | |
+radeon_pm_info_handler(SYSCTL_HANDLER_ARGS) | |
+{ | |
+ struct sbuf m; | |
+ struct drm_device *dev; | |
+ struct radeon_device *rdev; | |
+ int error; | |
+ | |
+ dev = arg1; | |
+ rdev = dev->dev_private; | |
+ if (rdev == NULL) | |
+ return (EBUSY); | |
+ | |
+ error = sysctl_wire_old_buffer(req, 0); | |
+ if (error != 0) | |
+ return (error); | |
+ sbuf_new_for_sysctl(&m, NULL, 128, req); | |
+ | |
+ sbuf_printf(&m, "default engine clock: %u0 kHz\n", rdev->pm.default_sclk); | |
+ /* radeon_get_engine_clock is not reliable on APUs so just print the current clock */ | |
+ if ((rdev->family >= CHIP_PALM) && (rdev->flags & RADEON_IS_IGP)) | |
+ sbuf_printf(&m, "current engine clock: %u0 kHz\n", rdev->pm.current_sclk); | |
+ else | |
+ sbuf_printf(&m, "current engine clock: %u0 kHz\n", radeon_get_engine_clock(rdev)); | |
+ sbuf_printf(&m, "default memory clock: %u0 kHz\n", rdev->pm.default_mclk); | |
+ if (rdev->asic->pm.get_memory_clock) | |
+ sbuf_printf(&m, "current memory clock: %u0 kHz\n", radeon_get_memory_clock(rdev)); | |
+ if (rdev->pm.current_vddc) | |
+ sbuf_printf(&m, "voltage: %u mV\n", rdev->pm.current_vddc); | |
+ if (rdev->asic->pm.get_pcie_lanes) | |
+ sbuf_printf(&m, "PCIE lanes: %d\n", radeon_get_pcie_lanes(rdev)); | |
+ | |
+ if (error == 0) | |
+ error = sbuf_finish(&m); | |
+ sbuf_delete(&m); | |
+ return (error); | |
+} | |
+ | |
+int | |
+radeon_pm_sysctl_init(struct drm_device *dev, struct sysctl_ctx_list *ctx, | |
+ struct sysctl_oid *top) | |
+{ | |
+ | |
+ (void)SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(top), OID_AUTO, | |
+ "power_profile", CTLTYPE_STRING | CTLFLAG_RW, dev, 0, | |
+ power_profile_handler, "A", NULL); | |
+ | |
+ (void)SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(top), OID_AUTO, | |
+ "power_method", CTLTYPE_STRING | CTLFLAG_RW, dev, 0, | |
+ power_method_handler, "A", NULL); | |
+ | |
+ (void)SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(top), OID_AUTO, | |
+ "pm_info", CTLTYPE_STRING | CTLFLAG_RD, dev, 0, | |
+ radeon_pm_info_handler, "A", NULL); | |
+ | |
+ (void)SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(top), OID_AUTO, | |
+ "temperature", CTLTYPE_INT | CTLFLAG_RD, dev, 0, | |
+ radeon_temp_handler, "IK", NULL); | |
+ | |
+ return (0); | |
+} | |
+ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment