]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
hwmon: (aspeed-pwm-tacho) mutex for tach reading
authorLoic Prylli <lprylli@netflix.com>
Fri, 3 Nov 2023 10:30:55 +0000 (11:30 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 23 Feb 2024 07:42:19 +0000 (08:42 +0100)
[ Upstream commit 1168491e7f53581ba7b6014a39a49cfbbb722feb ]

the ASPEED_PTCR_RESULT Register can only hold the result for a
single fan input. Adding a mutex to protect the register until the
reading is done.

Signed-off-by: Loic Prylli <lprylli@netflix.com>
Signed-off-by: Alexander Hansen <alexander.hansen@9elements.com>
Fixes: 2d7a548a3eff ("drivers: hwmon: Support for ASPEED PWM/Fan tach")
Link: https://lore.kernel.org/r/121d888762a1232ef403cf35230ccf7b3887083a.1699007401.git.alexander.hansen@9elements.com
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/hwmon/aspeed-pwm-tacho.c

index 3d8239fd66ed6107f1cc76eac8cd2f72dd25a9cd..3dc97041a704c44306f3168d8c02ae7dbbaf12ce 100644 (file)
@@ -194,6 +194,8 @@ struct aspeed_pwm_tacho_data {
        u8 fan_tach_ch_source[16];
        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 };
@@ -528,6 +530,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);
 
@@ -545,6 +549,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;
@@ -904,6 +910,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))