Commit 5ca243c2 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'hwmon-for-v6.8-rc4' of...

Merge tag 'hwmon-for-v6.8-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging

Pull hwmon fixes from Guenter Roeck:

 - coretemp: Various fixes, and increase number of supported CPU cores

 - aspeed-pwm-tacho: Add missing mutex protection

* tag 'hwmon-for-v6.8-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging:
  hwmon: (coretemp) Enlarge per package core count limit
  hwmon: (coretemp) Fix bogus core_id to attr name mapping
  hwmon: (coretemp) Fix out-of-bounds memory access
  hwmon: (aspeed-pwm-tacho) mutex for tach reading
parents eb747bcc 34cf8c65
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -195,6 +195,8 @@ struct aspeed_pwm_tacho_data {
	u8 fan_tach_ch_source[MAX_ASPEED_FAN_TACH_CHANNELS];
	struct aspeed_cooling_device *cdev[8];
	const struct attribute_group *groups[3];
	/* protects access to shared ASPEED_PTCR_RESULT */
	struct mutex tach_lock;
};

enum type { TYPEM, TYPEN, TYPEO };
@@ -529,6 +531,8 @@ static int aspeed_get_fan_tach_ch_rpm(struct aspeed_pwm_tacho_data *priv,
	u8 fan_tach_ch_source, type, mode, both;
	int ret;

	mutex_lock(&priv->tach_lock);

	regmap_write(priv->regmap, ASPEED_PTCR_TRIGGER, 0);
	regmap_write(priv->regmap, ASPEED_PTCR_TRIGGER, 0x1 << fan_tach_ch);

@@ -546,6 +550,8 @@ static int aspeed_get_fan_tach_ch_rpm(struct aspeed_pwm_tacho_data *priv,
		ASPEED_RPM_STATUS_SLEEP_USEC,
		usec);

	mutex_unlock(&priv->tach_lock);

	/* return -ETIMEDOUT if we didn't get an answer. */
	if (ret)
		return ret;
@@ -915,6 +921,7 @@ static int aspeed_pwm_tacho_probe(struct platform_device *pdev)
	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
	if (!priv)
		return -ENOMEM;
	mutex_init(&priv->tach_lock);
	priv->regmap = devm_regmap_init(dev, NULL, (__force void *)regs,
			&aspeed_pwm_tacho_regmap_config);
	if (IS_ERR(priv->regmap))
+22 −20
Original line number Diff line number Diff line
@@ -41,7 +41,7 @@ MODULE_PARM_DESC(tjmax, "TjMax value in degrees Celsius");

#define PKG_SYSFS_ATTR_NO	1	/* Sysfs attribute for package temp */
#define BASE_SYSFS_ATTR_NO	2	/* Sysfs Base attr no for coretemp */
#define NUM_REAL_CORES		128	/* Number of Real cores per cpu */
#define NUM_REAL_CORES		512	/* Number of Real cores per cpu */
#define CORETEMP_NAME_LENGTH	28	/* String Length of attrs */
#define MAX_CORE_ATTRS		4	/* Maximum no of basic attrs */
#define TOTAL_ATTRS		(MAX_CORE_ATTRS + 1)
@@ -419,7 +419,7 @@ static ssize_t show_temp(struct device *dev,
}

static int create_core_attrs(struct temp_data *tdata, struct device *dev,
			     int attr_no)
			     int index)
{
	int i;
	static ssize_t (*const rd_ptr[TOTAL_ATTRS]) (struct device *dev,
@@ -431,13 +431,20 @@ static int create_core_attrs(struct temp_data *tdata, struct device *dev,
	};

	for (i = 0; i < tdata->attr_size; i++) {
		/*
		 * We map the attr number to core id of the CPU
		 * The attr number is always core id + 2
		 * The Pkgtemp will always show up as temp1_*, if available
		 */
		int attr_no = tdata->is_pkg_data ? 1 : tdata->cpu_core_id + 2;

		snprintf(tdata->attr_name[i], CORETEMP_NAME_LENGTH,
			 "temp%d_%s", attr_no, suffixes[i]);
		sysfs_attr_init(&tdata->sd_attrs[i].dev_attr.attr);
		tdata->sd_attrs[i].dev_attr.attr.name = tdata->attr_name[i];
		tdata->sd_attrs[i].dev_attr.attr.mode = 0444;
		tdata->sd_attrs[i].dev_attr.show = rd_ptr[i];
		tdata->sd_attrs[i].index = attr_no;
		tdata->sd_attrs[i].index = index;
		tdata->attrs[i] = &tdata->sd_attrs[i].dev_attr.attr;
	}
	tdata->attr_group.attrs = tdata->attrs;
@@ -495,30 +502,25 @@ static int create_core_data(struct platform_device *pdev, unsigned int cpu,
	struct platform_data *pdata = platform_get_drvdata(pdev);
	struct cpuinfo_x86 *c = &cpu_data(cpu);
	u32 eax, edx;
	int err, index, attr_no;
	int err, index;

	if (!housekeeping_cpu(cpu, HK_TYPE_MISC))
		return 0;

	/*
	 * Find attr number for sysfs:
	 * We map the attr number to core id of the CPU
	 * The attr number is always core id + 2
	 * The Pkgtemp will always show up as temp1_*, if available
	 * Get the index of tdata in pdata->core_data[]
	 * tdata for package: pdata->core_data[1]
	 * tdata for core: pdata->core_data[2] .. pdata->core_data[NUM_REAL_CORES + 1]
	 */
	if (pkg_flag) {
		attr_no = PKG_SYSFS_ATTR_NO;
		index = PKG_SYSFS_ATTR_NO;
	} else {
		index = ida_alloc(&pdata->ida, GFP_KERNEL);
		index = ida_alloc_max(&pdata->ida, NUM_REAL_CORES - 1, GFP_KERNEL);
		if (index < 0)
			return index;
		pdata->cpu_map[index] = topology_core_id(cpu);
		attr_no = index + BASE_SYSFS_ATTR_NO;
	}

	if (attr_no > MAX_CORE_DATA - 1) {
		err = -ERANGE;
		goto ida_free;
		pdata->cpu_map[index] = topology_core_id(cpu);
		index += BASE_SYSFS_ATTR_NO;
	}

	tdata = init_temp_data(cpu, pkg_flag);
@@ -544,20 +546,20 @@ static int create_core_data(struct platform_device *pdev, unsigned int cpu,
		if (get_ttarget(tdata, &pdev->dev) >= 0)
			tdata->attr_size++;

	pdata->core_data[attr_no] = tdata;
	pdata->core_data[index] = tdata;

	/* Create sysfs interfaces */
	err = create_core_attrs(tdata, pdata->hwmon_dev, attr_no);
	err = create_core_attrs(tdata, pdata->hwmon_dev, index);
	if (err)
		goto exit_free;

	return 0;
exit_free:
	pdata->core_data[attr_no] = NULL;
	pdata->core_data[index] = NULL;
	kfree(tdata);
ida_free:
	if (!pkg_flag)
		ida_free(&pdata->ida, index);
		ida_free(&pdata->ida, index - BASE_SYSFS_ATTR_NO);
	return err;
}