]> Git Repo - linux.git/blobdiff - drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
Merge branch 'x86-timers-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[linux.git] / drivers / gpu / drm / amd / amdgpu / amdgpu_pm.c
index 18873c2286f9ec20299370cada0be11521b7c8d4..361975cf45a9ffdd61635e0f8eb93f944b52f66b 100644 (file)
@@ -719,7 +719,6 @@ static ssize_t amdgpu_set_pp_power_profile_mode(struct device *dev,
                                count = -EINVAL;
                                goto fail;
                        }
-                       pr_info("value is %ld \n", parameter[parameter_size]);
                        parameter_size++;
                        while (isspace(*tmp_str))
                                tmp_str++;
@@ -735,161 +734,6 @@ fail:
        return -EINVAL;
 }
 
-static ssize_t amdgpu_get_pp_power_profile(struct device *dev,
-               char *buf, struct amd_pp_profile *query)
-{
-       struct drm_device *ddev = dev_get_drvdata(dev);
-       struct amdgpu_device *adev = ddev->dev_private;
-       int ret = 0xff;
-
-       if (adev->powerplay.pp_funcs->get_power_profile_state)
-               ret = amdgpu_dpm_get_power_profile_state(
-                               adev, query);
-
-       if (ret)
-               return ret;
-
-       return snprintf(buf, PAGE_SIZE,
-                       "%d %d %d %d %d\n",
-                       query->min_sclk / 100,
-                       query->min_mclk / 100,
-                       query->activity_threshold,
-                       query->up_hyst,
-                       query->down_hyst);
-}
-
-static ssize_t amdgpu_get_pp_gfx_power_profile(struct device *dev,
-               struct device_attribute *attr,
-               char *buf)
-{
-       struct amd_pp_profile query = {0};
-
-       query.type = AMD_PP_GFX_PROFILE;
-
-       return amdgpu_get_pp_power_profile(dev, buf, &query);
-}
-
-static ssize_t amdgpu_get_pp_compute_power_profile(struct device *dev,
-               struct device_attribute *attr,
-               char *buf)
-{
-       struct amd_pp_profile query = {0};
-
-       query.type = AMD_PP_COMPUTE_PROFILE;
-
-       return amdgpu_get_pp_power_profile(dev, buf, &query);
-}
-
-static ssize_t amdgpu_set_pp_power_profile(struct device *dev,
-               const char *buf,
-               size_t count,
-               struct amd_pp_profile *request)
-{
-       struct drm_device *ddev = dev_get_drvdata(dev);
-       struct amdgpu_device *adev = ddev->dev_private;
-       uint32_t loop = 0;
-       char *sub_str, buf_cpy[128], *tmp_str;
-       const char delimiter[3] = {' ', '\n', '\0'};
-       long int value;
-       int ret = 0xff;
-
-       if (strncmp("reset", buf, strlen("reset")) == 0) {
-               if (adev->powerplay.pp_funcs->reset_power_profile_state)
-                       ret = amdgpu_dpm_reset_power_profile_state(
-                                       adev, request);
-               if (ret) {
-                       count = -EINVAL;
-                       goto fail;
-               }
-               return count;
-       }
-
-       if (strncmp("set", buf, strlen("set")) == 0) {
-               if (adev->powerplay.pp_funcs->set_power_profile_state)
-                       ret = amdgpu_dpm_set_power_profile_state(
-                                       adev, request);
-
-               if (ret) {
-                       count = -EINVAL;
-                       goto fail;
-               }
-               return count;
-       }
-
-       if (count + 1 >= 128) {
-               count = -EINVAL;
-               goto fail;
-       }
-
-       memcpy(buf_cpy, buf, count + 1);
-       tmp_str = buf_cpy;
-
-       while (tmp_str[0]) {
-               sub_str = strsep(&tmp_str, delimiter);
-               ret = kstrtol(sub_str, 0, &value);
-               if (ret) {
-                       count = -EINVAL;
-                       goto fail;
-               }
-
-               switch (loop) {
-               case 0:
-                       /* input unit MHz convert to dpm table unit 10KHz*/
-                       request->min_sclk = (uint32_t)value * 100;
-                       break;
-               case 1:
-                       /* input unit MHz convert to dpm table unit 10KHz*/
-                       request->min_mclk = (uint32_t)value * 100;
-                       break;
-               case 2:
-                       request->activity_threshold = (uint16_t)value;
-                       break;
-               case 3:
-                       request->up_hyst = (uint8_t)value;
-                       break;
-               case 4:
-                       request->down_hyst = (uint8_t)value;
-                       break;
-               default:
-                       break;
-               }
-
-               loop++;
-       }
-       if (adev->powerplay.pp_funcs->set_power_profile_state)
-               ret = amdgpu_dpm_set_power_profile_state(adev, request);
-
-       if (ret)
-               count = -EINVAL;
-
-fail:
-       return count;
-}
-
-static ssize_t amdgpu_set_pp_gfx_power_profile(struct device *dev,
-               struct device_attribute *attr,
-               const char *buf,
-               size_t count)
-{
-       struct amd_pp_profile request = {0};
-
-       request.type = AMD_PP_GFX_PROFILE;
-
-       return amdgpu_set_pp_power_profile(dev, buf, count, &request);
-}
-
-static ssize_t amdgpu_set_pp_compute_power_profile(struct device *dev,
-               struct device_attribute *attr,
-               const char *buf,
-               size_t count)
-{
-       struct amd_pp_profile request = {0};
-
-       request.type = AMD_PP_COMPUTE_PROFILE;
-
-       return amdgpu_set_pp_power_profile(dev, buf, count, &request);
-}
-
 static DEVICE_ATTR(power_dpm_state, S_IRUGO | S_IWUSR, amdgpu_get_dpm_state, amdgpu_set_dpm_state);
 static DEVICE_ATTR(power_dpm_force_performance_level, S_IRUGO | S_IWUSR,
                   amdgpu_get_dpm_forced_performance_level,
@@ -917,12 +761,6 @@ static DEVICE_ATTR(pp_sclk_od, S_IRUGO | S_IWUSR,
 static DEVICE_ATTR(pp_mclk_od, S_IRUGO | S_IWUSR,
                amdgpu_get_pp_mclk_od,
                amdgpu_set_pp_mclk_od);
-static DEVICE_ATTR(pp_gfx_power_profile, S_IRUGO | S_IWUSR,
-               amdgpu_get_pp_gfx_power_profile,
-               amdgpu_set_pp_gfx_power_profile);
-static DEVICE_ATTR(pp_compute_power_profile, S_IRUGO | S_IWUSR,
-               amdgpu_get_pp_compute_power_profile,
-               amdgpu_set_pp_compute_power_profile);
 static DEVICE_ATTR(pp_power_profile_mode, S_IRUGO | S_IWUSR,
                amdgpu_get_pp_power_profile_mode,
                amdgpu_set_pp_power_profile_mode);
@@ -936,17 +774,23 @@ static ssize_t amdgpu_hwmon_show_temp(struct device *dev,
 {
        struct amdgpu_device *adev = dev_get_drvdata(dev);
        struct drm_device *ddev = adev->ddev;
-       int temp;
+       int r, temp, size = sizeof(temp);
 
        /* Can't get temperature when the card is off */
        if  ((adev->flags & AMD_IS_PX) &&
             (ddev->switch_power_state != DRM_SWITCH_POWER_ON))
                return -EINVAL;
 
-       if (!adev->powerplay.pp_funcs->get_temperature)
-               temp = 0;
-       else
-               temp = amdgpu_dpm_get_temperature(adev);
+       /* sanity check PP is enabled */
+       if (!(adev->powerplay.pp_funcs &&
+             adev->powerplay.pp_funcs->read_sensor))
+               return -EINVAL;
+
+       /* get the temperature */
+       r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GPU_TEMP,
+                                  (void *)&temp, &size);
+       if (r)
+               return r;
 
        return snprintf(buf, PAGE_SIZE, "%d\n", temp);
 }
@@ -1096,6 +940,175 @@ static ssize_t amdgpu_hwmon_get_fan1_input(struct device *dev,
        return sprintf(buf, "%i\n", speed);
 }
 
+static ssize_t amdgpu_hwmon_show_vddgfx(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct amdgpu_device *adev = dev_get_drvdata(dev);
+       struct drm_device *ddev = adev->ddev;
+       u32 vddgfx;
+       int r, size = sizeof(vddgfx);
+
+       /* Can't get voltage when the card is off */
+       if  ((adev->flags & AMD_IS_PX) &&
+            (ddev->switch_power_state != DRM_SWITCH_POWER_ON))
+               return -EINVAL;
+
+       /* sanity check PP is enabled */
+       if (!(adev->powerplay.pp_funcs &&
+             adev->powerplay.pp_funcs->read_sensor))
+             return -EINVAL;
+
+       /* get the voltage */
+       r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_VDDGFX,
+                                  (void *)&vddgfx, &size);
+       if (r)
+               return r;
+
+       return snprintf(buf, PAGE_SIZE, "%d\n", vddgfx);
+}
+
+static ssize_t amdgpu_hwmon_show_vddgfx_label(struct device *dev,
+                                             struct device_attribute *attr,
+                                             char *buf)
+{
+       return snprintf(buf, PAGE_SIZE, "vddgfx\n");
+}
+
+static ssize_t amdgpu_hwmon_show_vddnb(struct device *dev,
+                                      struct device_attribute *attr,
+                                      char *buf)
+{
+       struct amdgpu_device *adev = dev_get_drvdata(dev);
+       struct drm_device *ddev = adev->ddev;
+       u32 vddnb;
+       int r, size = sizeof(vddnb);
+
+       /* only APUs have vddnb */
+       if  (adev->flags & AMD_IS_APU)
+               return -EINVAL;
+
+       /* Can't get voltage when the card is off */
+       if  ((adev->flags & AMD_IS_PX) &&
+            (ddev->switch_power_state != DRM_SWITCH_POWER_ON))
+               return -EINVAL;
+
+       /* sanity check PP is enabled */
+       if (!(adev->powerplay.pp_funcs &&
+             adev->powerplay.pp_funcs->read_sensor))
+             return -EINVAL;
+
+       /* get the voltage */
+       r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_VDDNB,
+                                  (void *)&vddnb, &size);
+       if (r)
+               return r;
+
+       return snprintf(buf, PAGE_SIZE, "%d\n", vddnb);
+}
+
+static ssize_t amdgpu_hwmon_show_vddnb_label(struct device *dev,
+                                             struct device_attribute *attr,
+                                             char *buf)
+{
+       return snprintf(buf, PAGE_SIZE, "vddnb\n");
+}
+
+static ssize_t amdgpu_hwmon_show_power_avg(struct device *dev,
+                                          struct device_attribute *attr,
+                                          char *buf)
+{
+       struct amdgpu_device *adev = dev_get_drvdata(dev);
+       struct drm_device *ddev = adev->ddev;
+       struct pp_gpu_power query = {0};
+       int r, size = sizeof(query);
+       unsigned uw;
+
+       /* Can't get power when the card is off */
+       if  ((adev->flags & AMD_IS_PX) &&
+            (ddev->switch_power_state != DRM_SWITCH_POWER_ON))
+               return -EINVAL;
+
+       /* sanity check PP is enabled */
+       if (!(adev->powerplay.pp_funcs &&
+             adev->powerplay.pp_funcs->read_sensor))
+             return -EINVAL;
+
+       /* get the voltage */
+       r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GPU_POWER,
+                                  (void *)&query, &size);
+       if (r)
+               return r;
+
+       /* convert to microwatts */
+       uw = (query.average_gpu_power >> 8) * 1000000;
+
+       return snprintf(buf, PAGE_SIZE, "%u\n", uw);
+}
+
+static ssize_t amdgpu_hwmon_show_power_cap_min(struct device *dev,
+                                        struct device_attribute *attr,
+                                        char *buf)
+{
+       return sprintf(buf, "%i\n", 0);
+}
+
+static ssize_t amdgpu_hwmon_show_power_cap_max(struct device *dev,
+                                        struct device_attribute *attr,
+                                        char *buf)
+{
+       struct amdgpu_device *adev = dev_get_drvdata(dev);
+       uint32_t limit = 0;
+
+       if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->get_power_limit) {
+               adev->powerplay.pp_funcs->get_power_limit(adev->powerplay.pp_handle, &limit, true);
+               return snprintf(buf, PAGE_SIZE, "%u\n", limit * 1000000);
+       } else {
+               return snprintf(buf, PAGE_SIZE, "\n");
+       }
+}
+
+static ssize_t amdgpu_hwmon_show_power_cap(struct device *dev,
+                                        struct device_attribute *attr,
+                                        char *buf)
+{
+       struct amdgpu_device *adev = dev_get_drvdata(dev);
+       uint32_t limit = 0;
+
+       if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->get_power_limit) {
+               adev->powerplay.pp_funcs->get_power_limit(adev->powerplay.pp_handle, &limit, false);
+               return snprintf(buf, PAGE_SIZE, "%u\n", limit * 1000000);
+       } else {
+               return snprintf(buf, PAGE_SIZE, "\n");
+       }
+}
+
+
+static ssize_t amdgpu_hwmon_set_power_cap(struct device *dev,
+               struct device_attribute *attr,
+               const char *buf,
+               size_t count)
+{
+       struct amdgpu_device *adev = dev_get_drvdata(dev);
+       int err;
+       u32 value;
+
+       err = kstrtou32(buf, 10, &value);
+       if (err)
+               return err;
+
+       value = value / 1000000; /* convert to Watt */
+       if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->set_power_limit) {
+               err = adev->powerplay.pp_funcs->set_power_limit(adev->powerplay.pp_handle, value);
+               if (err)
+                       return err;
+       } else {
+               return -EINVAL;
+       }
+
+       return count;
+}
+
 static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, amdgpu_hwmon_show_temp, NULL, 0);
 static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, amdgpu_hwmon_show_temp_thresh, NULL, 0);
 static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO, amdgpu_hwmon_show_temp_thresh, NULL, 1);
@@ -1104,6 +1117,14 @@ static SENSOR_DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR, amdgpu_hwmon_get_pwm1_
 static SENSOR_DEVICE_ATTR(pwm1_min, S_IRUGO, amdgpu_hwmon_get_pwm1_min, NULL, 0);
 static SENSOR_DEVICE_ATTR(pwm1_max, S_IRUGO, amdgpu_hwmon_get_pwm1_max, NULL, 0);
 static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, amdgpu_hwmon_get_fan1_input, NULL, 0);
+static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, amdgpu_hwmon_show_vddgfx, NULL, 0);
+static SENSOR_DEVICE_ATTR(in0_label, S_IRUGO, amdgpu_hwmon_show_vddgfx_label, NULL, 0);
+static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, amdgpu_hwmon_show_vddnb, NULL, 0);
+static SENSOR_DEVICE_ATTR(in1_label, S_IRUGO, amdgpu_hwmon_show_vddnb_label, NULL, 0);
+static SENSOR_DEVICE_ATTR(power1_average, S_IRUGO, amdgpu_hwmon_show_power_avg, NULL, 0);
+static SENSOR_DEVICE_ATTR(power1_cap_max, S_IRUGO, amdgpu_hwmon_show_power_cap_max, NULL, 0);
+static SENSOR_DEVICE_ATTR(power1_cap_min, S_IRUGO, amdgpu_hwmon_show_power_cap_min, NULL, 0);
+static SENSOR_DEVICE_ATTR(power1_cap, S_IRUGO | S_IWUSR, amdgpu_hwmon_show_power_cap, amdgpu_hwmon_set_power_cap, 0);
 
 static struct attribute *hwmon_attributes[] = {
        &sensor_dev_attr_temp1_input.dev_attr.attr,
@@ -1114,6 +1135,14 @@ static struct attribute *hwmon_attributes[] = {
        &sensor_dev_attr_pwm1_min.dev_attr.attr,
        &sensor_dev_attr_pwm1_max.dev_attr.attr,
        &sensor_dev_attr_fan1_input.dev_attr.attr,
+       &sensor_dev_attr_in0_input.dev_attr.attr,
+       &sensor_dev_attr_in0_label.dev_attr.attr,
+       &sensor_dev_attr_in1_input.dev_attr.attr,
+       &sensor_dev_attr_in1_label.dev_attr.attr,
+       &sensor_dev_attr_power1_average.dev_attr.attr,
+       &sensor_dev_attr_power1_cap_max.dev_attr.attr,
+       &sensor_dev_attr_power1_cap_min.dev_attr.attr,
+       &sensor_dev_attr_power1_cap.dev_attr.attr,
        NULL
 };
 
@@ -1124,9 +1153,19 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj,
        struct amdgpu_device *adev = dev_get_drvdata(dev);
        umode_t effective_mode = attr->mode;
 
-       /* no skipping for powerplay */
-       if (adev->powerplay.cgs_device)
-               return effective_mode;
+       /* handle non-powerplay limitations */
+       if (!adev->powerplay.pp_handle) {
+               /* Skip fan attributes if fan is not present */
+               if (adev->pm.no_fan &&
+                   (attr == &sensor_dev_attr_pwm1.dev_attr.attr ||
+                    attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr ||
+                    attr == &sensor_dev_attr_pwm1_max.dev_attr.attr ||
+                    attr == &sensor_dev_attr_pwm1_min.dev_attr.attr))
+                       return 0;
+               /* requires powerplay */
+               if (attr == &sensor_dev_attr_fan1_input.dev_attr.attr)
+                       return 0;
+       }
 
        /* Skip limit attributes if DPM is not enabled */
        if (!adev->pm.dpm_enabled &&
@@ -1138,14 +1177,6 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj,
             attr == &sensor_dev_attr_pwm1_min.dev_attr.attr))
                return 0;
 
-       /* Skip fan attributes if fan is not present */
-       if (adev->pm.no_fan &&
-           (attr == &sensor_dev_attr_pwm1.dev_attr.attr ||
-            attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr ||
-            attr == &sensor_dev_attr_pwm1_max.dev_attr.attr ||
-            attr == &sensor_dev_attr_pwm1_min.dev_attr.attr))
-               return 0;
-
        /* mask fan attributes if we have no bindings for this asic to expose */
        if ((!adev->powerplay.pp_funcs->get_fan_speed_percent &&
             attr == &sensor_dev_attr_pwm1.dev_attr.attr) || /* can't query fan */
@@ -1159,6 +1190,12 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj,
             attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr)) /* can't manage state */
                effective_mode &= ~S_IWUSR;
 
+       if ((adev->flags & AMD_IS_APU) &&
+           (attr == &sensor_dev_attr_power1_cap_max.dev_attr.attr ||
+            attr == &sensor_dev_attr_power1_cap_min.dev_attr.attr||
+            attr == &sensor_dev_attr_power1_cap.dev_attr.attr))
+               return 0;
+
        /* hide max/min values if we can't both query and manage the fan */
        if ((!adev->powerplay.pp_funcs->set_fan_speed_percent &&
             !adev->powerplay.pp_funcs->get_fan_speed_percent) &&
@@ -1166,8 +1203,10 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj,
             attr == &sensor_dev_attr_pwm1_min.dev_attr.attr))
                return 0;
 
-       /* requires powerplay */
-       if (attr == &sensor_dev_attr_fan1_input.dev_attr.attr)
+       /* only APUs have vddnb */
+       if (!(adev->flags & AMD_IS_APU) &&
+           (attr == &sensor_dev_attr_in1_input.dev_attr.attr ||
+            attr == &sensor_dev_attr_in1_label.dev_attr.attr))
                return 0;
 
        return effective_mode;
@@ -1190,13 +1229,15 @@ void amdgpu_dpm_thermal_work_handler(struct work_struct *work)
                             pm.dpm.thermal.work);
        /* switch to the thermal state */
        enum amd_pm_state_type dpm_state = POWER_STATE_TYPE_INTERNAL_THERMAL;
+       int temp, size = sizeof(temp);
 
        if (!adev->pm.dpm_enabled)
                return;
 
-       if (adev->powerplay.pp_funcs->get_temperature) {
-               int temp = amdgpu_dpm_get_temperature(adev);
-
+       if (adev->powerplay.pp_funcs &&
+           adev->powerplay.pp_funcs->read_sensor &&
+           !amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GPU_TEMP,
+                                   (void *)&temp, &size)) {
                if (temp < adev->pm.dpm.thermal.min_temp)
                        /* switch back the user state */
                        dpm_state = adev->pm.dpm.user_state;
@@ -1496,9 +1537,6 @@ int amdgpu_pm_sysfs_init(struct amdgpu_device *adev)
        if (adev->pm.dpm_enabled == 0)
                return 0;
 
-       if (adev->powerplay.pp_funcs->get_temperature == NULL)
-               return 0;
-
        adev->pm.int_hwmon_dev = hwmon_device_register_with_groups(adev->dev,
                                                                   DRIVER_NAME, adev,
                                                                   hwmon_groups);
@@ -1567,21 +1605,6 @@ int amdgpu_pm_sysfs_init(struct amdgpu_device *adev)
                DRM_ERROR("failed to create device file pp_mclk_od\n");
                return ret;
        }
-       ret = device_create_file(adev->dev,
-                       &dev_attr_pp_gfx_power_profile);
-       if (ret) {
-               DRM_ERROR("failed to create device file "
-                               "pp_gfx_power_profile\n");
-               return ret;
-       }
-       ret = device_create_file(adev->dev,
-                       &dev_attr_pp_compute_power_profile);
-       if (ret) {
-               DRM_ERROR("failed to create device file "
-                               "pp_compute_power_profile\n");
-               return ret;
-       }
-
        ret = device_create_file(adev->dev,
                        &dev_attr_pp_power_profile_mode);
        if (ret) {
@@ -1627,10 +1650,6 @@ void amdgpu_pm_sysfs_fini(struct amdgpu_device *adev)
        device_remove_file(adev->dev, &dev_attr_pp_dpm_pcie);
        device_remove_file(adev->dev, &dev_attr_pp_sclk_od);
        device_remove_file(adev->dev, &dev_attr_pp_mclk_od);
-       device_remove_file(adev->dev,
-                       &dev_attr_pp_gfx_power_profile);
-       device_remove_file(adev->dev,
-                       &dev_attr_pp_compute_power_profile);
        device_remove_file(adev->dev,
                        &dev_attr_pp_power_profile_mode);
        device_remove_file(adev->dev,
This page took 0.053791 seconds and 4 git commands to generate.