]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
hwmon: (occ) fix unaligned accesses
authorArnd Bergmann <arnd@arndb.de>
Tue, 10 Jun 2025 09:25:49 +0000 (11:25 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 27 Jun 2025 10:04:21 +0000 (11:04 +0100)
[ Upstream commit 2c021b45c154958566aad0cae9f74ab26a2d5732 ]

Passing a pointer to an unaligned integer as a function argument is
undefined behavior:

drivers/hwmon/occ/common.c:492:27: warning: taking address of packed member 'accumulator' of class or structure 'power_sensor_2' may result in an unaligned pointer value [-Waddress-of-packed-member]
  492 |   val = occ_get_powr_avg(&power->accumulator,
      |                           ^~~~~~~~~~~~~~~~~~
drivers/hwmon/occ/common.c:493:13: warning: taking address of packed member 'update_tag' of class or structure 'power_sensor_2' may result in an unaligned pointer value [-Waddress-of-packed-member]
  493 |            &power->update_tag);
      |             ^~~~~~~~~~~~~~~~~

Move the get_unaligned() calls out of the function and pass these
through argument registers instead.

Fixes: c10e753d43eb ("hwmon (occ): Add sensor types and versions")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Link: https://lore.kernel.org/r/20250610092553.2641094-1-arnd@kernel.org
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/hwmon/occ/common.c

index 44980946281c232a43f0bcb6b6e79d10a9951946..51bf560ef20b13a67d1ffc30d18debe41ef8483e 100644 (file)
@@ -468,12 +468,10 @@ static ssize_t occ_show_power_1(struct device *dev,
        return snprintf(buf, PAGE_SIZE - 1, "%llu\n", val);
 }
 
-static u64 occ_get_powr_avg(u64 *accum, u32 *samples)
+static u64 occ_get_powr_avg(u64 accum, u32 samples)
 {
-       u64 divisor = get_unaligned_be32(samples);
-
-       return (divisor == 0) ? 0 :
-               div64_u64(get_unaligned_be64(accum) * 1000000ULL, divisor);
+       return (samples == 0) ? 0 :
+               mul_u64_u32_div(accum, 1000000UL, samples);
 }
 
 static ssize_t occ_show_power_2(struct device *dev,
@@ -498,8 +496,8 @@ static ssize_t occ_show_power_2(struct device *dev,
                                get_unaligned_be32(&power->sensor_id),
                                power->function_id, power->apss_channel);
        case 1:
-               val = occ_get_powr_avg(&power->accumulator,
-                                      &power->update_tag);
+               val = occ_get_powr_avg(get_unaligned_be64(&power->accumulator),
+                                      get_unaligned_be32(&power->update_tag));
                break;
        case 2:
                val = (u64)get_unaligned_be32(&power->update_tag) *
@@ -536,8 +534,8 @@ static ssize_t occ_show_power_a0(struct device *dev,
                return snprintf(buf, PAGE_SIZE - 1, "%u_system\n",
                                get_unaligned_be32(&power->sensor_id));
        case 1:
-               val = occ_get_powr_avg(&power->system.accumulator,
-                                      &power->system.update_tag);
+               val = occ_get_powr_avg(get_unaligned_be64(&power->system.accumulator),
+                                      get_unaligned_be32(&power->system.update_tag));
                break;
        case 2:
                val = (u64)get_unaligned_be32(&power->system.update_tag) *
@@ -550,8 +548,8 @@ static ssize_t occ_show_power_a0(struct device *dev,
                return snprintf(buf, PAGE_SIZE - 1, "%u_proc\n",
                                get_unaligned_be32(&power->sensor_id));
        case 5:
-               val = occ_get_powr_avg(&power->proc.accumulator,
-                                      &power->proc.update_tag);
+               val = occ_get_powr_avg(get_unaligned_be64(&power->proc.accumulator),
+                                      get_unaligned_be32(&power->proc.update_tag));
                break;
        case 6:
                val = (u64)get_unaligned_be32(&power->proc.update_tag) *
@@ -564,8 +562,8 @@ static ssize_t occ_show_power_a0(struct device *dev,
                return snprintf(buf, PAGE_SIZE - 1, "%u_vdd\n",
                                get_unaligned_be32(&power->sensor_id));
        case 9:
-               val = occ_get_powr_avg(&power->vdd.accumulator,
-                                      &power->vdd.update_tag);
+               val = occ_get_powr_avg(get_unaligned_be64(&power->vdd.accumulator),
+                                      get_unaligned_be32(&power->vdd.update_tag));
                break;
        case 10:
                val = (u64)get_unaligned_be32(&power->vdd.update_tag) *
@@ -578,8 +576,8 @@ static ssize_t occ_show_power_a0(struct device *dev,
                return snprintf(buf, PAGE_SIZE - 1, "%u_vdn\n",
                                get_unaligned_be32(&power->sensor_id));
        case 13:
-               val = occ_get_powr_avg(&power->vdn.accumulator,
-                                      &power->vdn.update_tag);
+               val = occ_get_powr_avg(get_unaligned_be64(&power->vdn.accumulator),
+                                      get_unaligned_be32(&power->vdn.update_tag));
                break;
        case 14:
                val = (u64)get_unaligned_be32(&power->vdn.update_tag) *