Skip to content

Instantly share code, notes, and snippets.

@wethu
Created December 18, 2017 11:02
Show Gist options
  • Save wethu/fa91bc2bb295e2807e4778d67c55a0a4 to your computer and use it in GitHub Desktop.
Save wethu/fa91bc2bb295e2807e4778d67c55a0a4 to your computer and use it in GitHub Desktop.
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