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

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
...@@ -195,6 +195,8 @@ struct aspeed_pwm_tacho_data { ...@@ -195,6 +195,8 @@ struct aspeed_pwm_tacho_data {
u8 fan_tach_ch_source[MAX_ASPEED_FAN_TACH_CHANNELS]; u8 fan_tach_ch_source[MAX_ASPEED_FAN_TACH_CHANNELS];
struct aspeed_cooling_device *cdev[8]; struct aspeed_cooling_device *cdev[8];
const struct attribute_group *groups[3]; const struct attribute_group *groups[3];
/* protects access to shared ASPEED_PTCR_RESULT */
struct mutex tach_lock;
}; };
enum type { TYPEM, TYPEN, TYPEO }; enum type { TYPEM, TYPEN, TYPEO };
...@@ -529,6 +531,8 @@ static int aspeed_get_fan_tach_ch_rpm(struct aspeed_pwm_tacho_data *priv, ...@@ -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; u8 fan_tach_ch_source, type, mode, both;
int ret; int ret;
mutex_lock(&priv->tach_lock);
regmap_write(priv->regmap, ASPEED_PTCR_TRIGGER, 0); regmap_write(priv->regmap, ASPEED_PTCR_TRIGGER, 0);
regmap_write(priv->regmap, ASPEED_PTCR_TRIGGER, 0x1 << fan_tach_ch); 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, ...@@ -546,6 +550,8 @@ static int aspeed_get_fan_tach_ch_rpm(struct aspeed_pwm_tacho_data *priv,
ASPEED_RPM_STATUS_SLEEP_USEC, ASPEED_RPM_STATUS_SLEEP_USEC,
usec); usec);
mutex_unlock(&priv->tach_lock);
/* return -ETIMEDOUT if we didn't get an answer. */ /* return -ETIMEDOUT if we didn't get an answer. */
if (ret) if (ret)
return ret; return ret;
...@@ -915,6 +921,7 @@ static int aspeed_pwm_tacho_probe(struct platform_device *pdev) ...@@ -915,6 +921,7 @@ static int aspeed_pwm_tacho_probe(struct platform_device *pdev)
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv) if (!priv)
return -ENOMEM; return -ENOMEM;
mutex_init(&priv->tach_lock);
priv->regmap = devm_regmap_init(dev, NULL, (__force void *)regs, priv->regmap = devm_regmap_init(dev, NULL, (__force void *)regs,
&aspeed_pwm_tacho_regmap_config); &aspeed_pwm_tacho_regmap_config);
if (IS_ERR(priv->regmap)) if (IS_ERR(priv->regmap))
......
...@@ -41,7 +41,7 @@ MODULE_PARM_DESC(tjmax, "TjMax value in degrees Celsius"); ...@@ -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 PKG_SYSFS_ATTR_NO 1 /* Sysfs attribute for package temp */
#define BASE_SYSFS_ATTR_NO 2 /* Sysfs Base attr no for coretemp */ #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 CORETEMP_NAME_LENGTH 28 /* String Length of attrs */
#define MAX_CORE_ATTRS 4 /* Maximum no of basic attrs */ #define MAX_CORE_ATTRS 4 /* Maximum no of basic attrs */
#define TOTAL_ATTRS (MAX_CORE_ATTRS + 1) #define TOTAL_ATTRS (MAX_CORE_ATTRS + 1)
...@@ -419,7 +419,7 @@ static ssize_t show_temp(struct device *dev, ...@@ -419,7 +419,7 @@ static ssize_t show_temp(struct device *dev,
} }
static int create_core_attrs(struct temp_data *tdata, struct device *dev, static int create_core_attrs(struct temp_data *tdata, struct device *dev,
int attr_no) int index)
{ {
int i; int i;
static ssize_t (*const rd_ptr[TOTAL_ATTRS]) (struct device *dev, 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, ...@@ -431,13 +431,20 @@ static int create_core_attrs(struct temp_data *tdata, struct device *dev,
}; };
for (i = 0; i < tdata->attr_size; i++) { 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, snprintf(tdata->attr_name[i], CORETEMP_NAME_LENGTH,
"temp%d_%s", attr_no, suffixes[i]); "temp%d_%s", attr_no, suffixes[i]);
sysfs_attr_init(&tdata->sd_attrs[i].dev_attr.attr); 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.name = tdata->attr_name[i];
tdata->sd_attrs[i].dev_attr.attr.mode = 0444; tdata->sd_attrs[i].dev_attr.attr.mode = 0444;
tdata->sd_attrs[i].dev_attr.show = rd_ptr[i]; 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->attrs[i] = &tdata->sd_attrs[i].dev_attr.attr;
} }
tdata->attr_group.attrs = tdata->attrs; tdata->attr_group.attrs = tdata->attrs;
...@@ -495,30 +502,25 @@ static int create_core_data(struct platform_device *pdev, unsigned int cpu, ...@@ -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 platform_data *pdata = platform_get_drvdata(pdev);
struct cpuinfo_x86 *c = &cpu_data(cpu); struct cpuinfo_x86 *c = &cpu_data(cpu);
u32 eax, edx; u32 eax, edx;
int err, index, attr_no; int err, index;
if (!housekeeping_cpu(cpu, HK_TYPE_MISC)) if (!housekeeping_cpu(cpu, HK_TYPE_MISC))
return 0; return 0;
/* /*
* Find attr number for sysfs: * Get the index of tdata in pdata->core_data[]
* We map the attr number to core id of the CPU * tdata for package: pdata->core_data[1]
* The attr number is always core id + 2 * tdata for core: pdata->core_data[2] .. pdata->core_data[NUM_REAL_CORES + 1]
* The Pkgtemp will always show up as temp1_*, if available
*/ */
if (pkg_flag) { if (pkg_flag) {
attr_no = PKG_SYSFS_ATTR_NO; index = PKG_SYSFS_ATTR_NO;
} else { } else {
index = ida_alloc(&pdata->ida, GFP_KERNEL); index = ida_alloc_max(&pdata->ida, NUM_REAL_CORES - 1, GFP_KERNEL);
if (index < 0) if (index < 0)
return index; return index;
pdata->cpu_map[index] = topology_core_id(cpu);
attr_no = index + BASE_SYSFS_ATTR_NO;
}
if (attr_no > MAX_CORE_DATA - 1) { pdata->cpu_map[index] = topology_core_id(cpu);
err = -ERANGE; index += BASE_SYSFS_ATTR_NO;
goto ida_free;
} }
tdata = init_temp_data(cpu, pkg_flag); tdata = init_temp_data(cpu, pkg_flag);
...@@ -544,20 +546,20 @@ static int create_core_data(struct platform_device *pdev, unsigned int cpu, ...@@ -544,20 +546,20 @@ static int create_core_data(struct platform_device *pdev, unsigned int cpu,
if (get_ttarget(tdata, &pdev->dev) >= 0) if (get_ttarget(tdata, &pdev->dev) >= 0)
tdata->attr_size++; tdata->attr_size++;
pdata->core_data[attr_no] = tdata; pdata->core_data[index] = tdata;
/* Create sysfs interfaces */ /* Create sysfs interfaces */
err = create_core_attrs(tdata, pdata->hwmon_dev, attr_no); err = create_core_attrs(tdata, pdata->hwmon_dev, index);
if (err) if (err)
goto exit_free; goto exit_free;
return 0; return 0;
exit_free: exit_free:
pdata->core_data[attr_no] = NULL; pdata->core_data[index] = NULL;
kfree(tdata); kfree(tdata);
ida_free: ida_free:
if (!pkg_flag) if (!pkg_flag)
ida_free(&pdata->ida, index); ida_free(&pdata->ida, index - BASE_SYSFS_ATTR_NO);
return err; return err;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment