Beispiel #1
0
static int
nouveau_temp_write(struct device *dev, u32 attr, int channel, long val)
{
	struct drm_device *drm_dev = dev_get_drvdata(dev);
	struct nouveau_drm *drm = nouveau_drm(drm_dev);
	struct nvkm_therm *therm = nvxx_therm(&drm->client.device);

	if (!therm || !therm->attr_set)
		return -EOPNOTSUPP;

	switch (attr) {
	case hwmon_temp_max:
		return therm->attr_set(therm, NVKM_THERM_ATTR_THRS_DOWN_CLK,
					val / 1000);
	case hwmon_temp_max_hyst:
		return therm->attr_set(therm, NVKM_THERM_ATTR_THRS_DOWN_CLK_HYST,
					val / 1000);
	case hwmon_temp_crit:
		return therm->attr_set(therm, NVKM_THERM_ATTR_THRS_CRITICAL,
					val / 1000);
	case hwmon_temp_crit_hyst:
		return therm->attr_set(therm, NVKM_THERM_ATTR_THRS_CRITICAL_HYST,
					val / 1000);
	case hwmon_temp_emergency:
		return therm->attr_set(therm, NVKM_THERM_ATTR_THRS_SHUTDOWN,
					val / 1000);
	case hwmon_temp_emergency_hyst:
		return therm->attr_set(therm, NVKM_THERM_ATTR_THRS_SHUTDOWN_HYST,
					val / 1000);
	default:
		return -EOPNOTSUPP;
	}
}
Beispiel #2
0
static ssize_t
nouveau_hwmon_max_temp(struct device *d, struct device_attribute *a, char *buf)
{
	struct drm_device *dev = dev_get_drvdata(d);
	struct nouveau_drm *drm = nouveau_drm(dev);
	struct nvkm_therm *therm = nvxx_therm(&drm->device);

	return snprintf(buf, PAGE_SIZE, "%d\n",
	       therm->attr_get(therm, NVKM_THERM_ATTR_THRS_DOWN_CLK) * 1000);
}
Beispiel #3
0
static ssize_t
nouveau_hwmon_show_fan1_input(struct device *d, struct device_attribute *attr,
			      char *buf)
{
	struct drm_device *dev = dev_get_drvdata(d);
	struct nouveau_drm *drm = nouveau_drm(dev);
	struct nvkm_therm *therm = nvxx_therm(&drm->device);

	return snprintf(buf, PAGE_SIZE, "%d\n", nvkm_therm_fan_sense(therm));
}
Beispiel #4
0
static ssize_t
nouveau_hwmon_emergency_temp_hyst(struct device *d, struct device_attribute *a,
							char *buf)
{
	struct drm_device *dev = dev_get_drvdata(d);
	struct nouveau_drm *drm = nouveau_drm(dev);
	struct nvkm_therm *therm = nvxx_therm(&drm->client.device);

	return snprintf(buf, PAGE_SIZE, "%d\n",
	  therm->attr_get(therm, NVKM_THERM_ATTR_THRS_SHUTDOWN_HYST) * 1000);
}
Beispiel #5
0
static ssize_t
nouveau_hwmon_temp1_auto_point1_temp_hyst(struct device *d,
					  struct device_attribute *a, char *buf)
{
	struct drm_device *dev = dev_get_drvdata(d);
	struct nouveau_drm *drm = nouveau_drm(dev);
	struct nvkm_therm *therm = nvxx_therm(&drm->device);

	return snprintf(buf, PAGE_SIZE, "%d\n",
	 therm->attr_get(therm, NVKM_THERM_ATTR_THRS_FAN_BOOST_HYST) * 1000);
}
Beispiel #6
0
static ssize_t
nouveau_hwmon_show_temp(struct device *d, struct device_attribute *a, char *buf)
{
	struct drm_device *dev = dev_get_drvdata(d);
	struct nouveau_drm *drm = nouveau_drm(dev);
	struct nvkm_therm *therm = nvxx_therm(&drm->device);
	int temp = nvkm_therm_temp_get(therm);

	if (temp < 0)
		return temp;

	return snprintf(buf, PAGE_SIZE, "%d\n", temp * 1000);
}
Beispiel #7
0
static ssize_t
nouveau_hwmon_get_pwm1(struct device *d, struct device_attribute *a, char *buf)
{
	struct drm_device *dev = dev_get_drvdata(d);
	struct nouveau_drm *drm = nouveau_drm(dev);
	struct nvkm_therm *therm = nvxx_therm(&drm->device);
	int ret;

	ret = therm->fan_get(therm);
	if (ret < 0)
		return ret;

	return sprintf(buf, "%i\n", ret);
}
Beispiel #8
0
static ssize_t
nouveau_hwmon_get_pwm1_max(struct device *d,
			   struct device_attribute *a, char *buf)
{
	struct drm_device *dev = dev_get_drvdata(d);
	struct nouveau_drm *drm = nouveau_drm(dev);
	struct nvkm_therm *therm = nvxx_therm(&drm->device);
	int ret;

	ret = therm->attr_get(therm, NVKM_THERM_ATTR_FAN_MAX_DUTY);
	if (ret < 0)
		return ret;

	return sprintf(buf, "%i\n", ret);
}
Beispiel #9
0
static ssize_t
nouveau_hwmon_set_max_temp(struct device *d, struct device_attribute *a,
						const char *buf, size_t count)
{
	struct drm_device *dev = dev_get_drvdata(d);
	struct nouveau_drm *drm = nouveau_drm(dev);
	struct nvkm_therm *therm = nvxx_therm(&drm->device);
	long value;

	if (kstrtol(buf, 10, &value) == -EINVAL)
		return count;

	therm->attr_set(therm, NVKM_THERM_ATTR_THRS_DOWN_CLK, value / 1000);

	return count;
}
Beispiel #10
0
static umode_t
nouveau_fan_is_visible(const void *data, u32 attr, int channel)
{
	struct nouveau_drm *drm = nouveau_drm((struct drm_device *)data);
	struct nvkm_therm *therm = nvxx_therm(&drm->client.device);

	if (!therm || !therm->attr_get || nvkm_therm_fan_sense(therm) < 0)
		return 0;

	switch (attr) {
	case hwmon_fan_input:
		return 0444;
	default:
		return 0;
	}
}
Beispiel #11
0
int
nouveau_hwmon_init(struct drm_device *dev)
{
#if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE))
	struct nouveau_drm *drm = nouveau_drm(dev);
	struct nvkm_iccsense *iccsense = nvxx_iccsense(&drm->client.device);
	struct nvkm_therm *therm = nvxx_therm(&drm->client.device);
	struct nvkm_volt *volt = nvxx_volt(&drm->client.device);
	const struct attribute_group *special_groups[N_ATTR_GROUPS];
	struct nouveau_hwmon *hwmon;
	struct device *hwmon_dev;
	int ret = 0;
	int i = 0;

	if (!iccsense && !therm && !volt) {
		NV_DEBUG(drm, "Skipping hwmon registration\n");
		return 0;
	}

	hwmon = drm->hwmon = kzalloc(sizeof(*hwmon), GFP_KERNEL);
	if (!hwmon)
		return -ENOMEM;
	hwmon->dev = dev;

	if (therm && therm->attr_get && therm->attr_set) {
		if (nvkm_therm_temp_get(therm) >= 0)
			special_groups[i++] = &temp1_auto_point_sensor_group;
		if (therm->fan_get && therm->fan_get(therm) >= 0)
			special_groups[i++] = &pwm_fan_sensor_group;
	}

	special_groups[i] = 0;
	hwmon_dev = hwmon_device_register_with_info(dev->dev, "nouveau", dev,
							&nouveau_chip_info,
							special_groups);
	if (IS_ERR(hwmon_dev)) {
		ret = PTR_ERR(hwmon_dev);
		NV_ERROR(drm, "Unable to register hwmon device: %d\n", ret);
		return ret;
	}

	hwmon->hwmon = hwmon_dev;
	return 0;
#else
	return 0;
#endif
}
Beispiel #12
0
static int
nouveau_temp_read(struct device *dev, u32 attr, int channel, long *val)
{
	struct drm_device *drm_dev = dev_get_drvdata(dev);
	struct nouveau_drm *drm = nouveau_drm(drm_dev);
	struct nvkm_therm *therm = nvxx_therm(&drm->client.device);
	int ret;

	if (!therm || !therm->attr_get)
		return -EOPNOTSUPP;

	switch (attr) {
	case hwmon_temp_input:
		ret = nvkm_therm_temp_get(therm);
		*val = ret < 0 ? ret : (ret * 1000);
		break;
	case hwmon_temp_max:
		*val = therm->attr_get(therm, NVKM_THERM_ATTR_THRS_DOWN_CLK)
					* 1000;
		break;
	case hwmon_temp_max_hyst:
		*val = therm->attr_get(therm, NVKM_THERM_ATTR_THRS_DOWN_CLK_HYST)
					* 1000;
		break;
	case hwmon_temp_crit:
		*val = therm->attr_get(therm, NVKM_THERM_ATTR_THRS_CRITICAL)
					* 1000;
		break;
	case hwmon_temp_crit_hyst:
		*val = therm->attr_get(therm, NVKM_THERM_ATTR_THRS_CRITICAL_HYST)
					* 1000;
		break;
	case hwmon_temp_emergency:
		*val = therm->attr_get(therm, NVKM_THERM_ATTR_THRS_SHUTDOWN)
					* 1000;
		break;
	case hwmon_temp_emergency_hyst:
		*val = therm->attr_get(therm, NVKM_THERM_ATTR_THRS_SHUTDOWN_HYST)
					* 1000;
		break;
	default:
		return -EOPNOTSUPP;
	}

	return 0;
}
Beispiel #13
0
static ssize_t
nouveau_hwmon_set_temp1_auto_point1_temp_hyst(struct device *d,
					      struct device_attribute *a,
					      const char *buf, size_t count)
{
	struct drm_device *dev = dev_get_drvdata(d);
	struct nouveau_drm *drm = nouveau_drm(dev);
	struct nvkm_therm *therm = nvxx_therm(&drm->client.device);
	long value;

	if (kstrtol(buf, 10, &value) == -EINVAL)
		return count;

	therm->attr_set(therm, NVKM_THERM_ATTR_THRS_FAN_BOOST_HYST,
			value / 1000);

	return count;
}
Beispiel #14
0
static ssize_t
nouveau_hwmon_set_pwm1_max(struct device *d, struct device_attribute *a,
			   const char *buf, size_t count)
{
	struct drm_device *dev = dev_get_drvdata(d);
	struct nouveau_drm *drm = nouveau_drm(dev);
	struct nvkm_therm *therm = nvxx_therm(&drm->device);
	long value;
	int ret;

	if (kstrtol(buf, 10, &value) == -EINVAL)
		return -EINVAL;

	ret = therm->attr_set(therm, NVKM_THERM_ATTR_FAN_MAX_DUTY, value);
	if (ret < 0)
		return ret;

	return count;
}
Beispiel #15
0
static ssize_t
nouveau_hwmon_set_pwm1(struct device *d, struct device_attribute *a,
		       const char *buf, size_t count)
{
	struct drm_device *dev = dev_get_drvdata(d);
	struct nouveau_drm *drm = nouveau_drm(dev);
	struct nvkm_therm *therm = nvxx_therm(&drm->device);
	int ret = -ENODEV;
	long value;

	if (kstrtol(buf, 10, &value) == -EINVAL)
		return -EINVAL;

	ret = therm->fan_set(therm, value);
	if (ret)
		return ret;

	return count;
}
Beispiel #16
0
static int
nouveau_pwm_write(struct device *dev, u32 attr, int channel, long val)
{
	struct drm_device *drm_dev = dev_get_drvdata(dev);
	struct nouveau_drm *drm = nouveau_drm(drm_dev);
	struct nvkm_therm *therm = nvxx_therm(&drm->client.device);

	if (!therm || !therm->attr_set)
		return -EOPNOTSUPP;

	switch (attr) {
	case hwmon_pwm_input:
		return therm->fan_set(therm, val);
	case hwmon_pwm_enable:
		return therm->attr_set(therm, NVKM_THERM_ATTR_FAN_MODE, val);
	default:
		return -EOPNOTSUPP;
	}
}
Beispiel #17
0
static int
nouveau_fan_read(struct device *dev, u32 attr, int channel, long *val)
{
	struct drm_device *drm_dev = dev_get_drvdata(dev);
	struct nouveau_drm *drm = nouveau_drm(drm_dev);
	struct nvkm_therm *therm = nvxx_therm(&drm->client.device);

	if (!therm)
		return -EOPNOTSUPP;

	switch (attr) {
	case hwmon_fan_input:
		*val = nvkm_therm_fan_sense(therm);
		break;
	default:
		return -EOPNOTSUPP;
	}

	return 0;
}
Beispiel #18
0
static ssize_t
nouveau_hwmon_set_pwm1_enable(struct device *d, struct device_attribute *a,
			   const char *buf, size_t count)
{
	struct drm_device *dev = dev_get_drvdata(d);
	struct nouveau_drm *drm = nouveau_drm(dev);
	struct nvkm_therm *therm = nvxx_therm(&drm->device);
	long value;
	int ret;

	ret = kstrtol(buf, 10, &value);
	if (ret)
		return ret;

	ret = therm->attr_set(therm, NVKM_THERM_ATTR_FAN_MODE, value);
	if (ret)
		return ret;
	else
		return count;
}
Beispiel #19
0
static umode_t
nouveau_temp_is_visible(const void *data, u32 attr, int channel)
{
	struct nouveau_drm *drm = nouveau_drm((struct drm_device *)data);
	struct nvkm_therm *therm = nvxx_therm(&drm->client.device);

	if (!therm || !therm->attr_get || nvkm_therm_temp_get(therm) < 0)
		return 0;

	switch (attr) {
	case hwmon_temp_input:
		return 0444;
	case hwmon_temp_max:
	case hwmon_temp_max_hyst:
	case hwmon_temp_crit:
	case hwmon_temp_crit_hyst:
	case hwmon_temp_emergency:
	case hwmon_temp_emergency_hyst:
		return 0644;
	default:
		return 0;
	}
}
Beispiel #20
0
int
nouveau_hwmon_init(struct drm_device *dev)
{
#if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE))
	struct nouveau_drm *drm = nouveau_drm(dev);
	struct nvkm_therm *therm = nvxx_therm(&drm->device);
	struct nvkm_volt *volt = nvxx_volt(&drm->device);
	struct nvkm_iccsense *iccsense = nvxx_iccsense(&drm->device);
	struct nouveau_hwmon *hwmon;
	struct device *hwmon_dev;
	int ret = 0;

	hwmon = drm->hwmon = kzalloc(sizeof(*hwmon), GFP_KERNEL);
	if (!hwmon)
		return -ENOMEM;
	hwmon->dev = dev;

	hwmon_dev = hwmon_device_register(dev->dev);
	if (IS_ERR(hwmon_dev)) {
		ret = PTR_ERR(hwmon_dev);
		NV_ERROR(drm, "Unable to register hwmon device: %d\n", ret);
		return ret;
	}
	dev_set_drvdata(hwmon_dev, dev);

	/* set the default attributes */
	ret = sysfs_create_group(&hwmon_dev->kobj, &hwmon_default_attrgroup);
	if (ret)
		goto error;

	if (therm && therm->attr_get && therm->attr_set) {
		/* if the card has a working thermal sensor */
		if (nvkm_therm_temp_get(therm) >= 0) {
			ret = sysfs_create_group(&hwmon_dev->kobj, &hwmon_temp_attrgroup);
			if (ret)
				goto error;
		}

		/* if the card has a pwm fan */
		/*XXX: incorrect, need better detection for this, some boards have
		 *     the gpio entries for pwm fan control even when there's no
		 *     actual fan connected to it... therm table? */
		if (therm->fan_get && therm->fan_get(therm) >= 0) {
			ret = sysfs_create_group(&hwmon_dev->kobj,
						 &hwmon_pwm_fan_attrgroup);
			if (ret)
				goto error;
		}
	}

	/* if the card can read the fan rpm */
	if (therm && nvkm_therm_fan_sense(therm) >= 0) {
		ret = sysfs_create_group(&hwmon_dev->kobj,
					 &hwmon_fan_rpm_attrgroup);
		if (ret)
			goto error;
	}

	if (volt && nvkm_volt_get(volt) >= 0) {
		ret = sysfs_create_group(&hwmon_dev->kobj,
					 &hwmon_in0_attrgroup);

		if (ret)
			goto error;
	}

	if (iccsense && iccsense->data_valid && !list_empty(&iccsense->rails)) {
		ret = sysfs_create_group(&hwmon_dev->kobj,
					 &hwmon_power_attrgroup);
		if (ret)
			goto error;
	}

	hwmon->hwmon = hwmon_dev;

	return 0;

error:
	NV_ERROR(drm, "Unable to create some hwmon sysfs files: %d\n", ret);
	hwmon_device_unregister(hwmon_dev);
	hwmon->hwmon = NULL;
	return ret;
#else
	return 0;
#endif
}