Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

firmware: exynos-acpm: Drop fake 'const' on handle pointer

All the functions operating on the 'handle' pointer are claiming it is a
pointer to const thus they should not modify the handle. In fact that's
a false statement, because first thing these functions do is drop the
cast to const with container_of:

struct acpm_info *acpm = handle_to_acpm_info(handle);

And with such cast the handle is easily writable with simple:

acpm->handle.ops.pmic_ops.read_reg = NULL;

The code is not correct logically, either, because functions like
acpm_get_by_node() and acpm_handle_put() are meant to modify the handle
reference counting, thus they must modify the handle. Modification here
happens anyway, even if the reference counting is stored in the
container which the handle is part of.

The code does not have actual visible bug, but incorrect 'const'
annotations could lead to incorrect compiler decisions.

Fixes: a88927b534ba ("firmware: add Exynos ACPM protocol driver")
Cc: stable@vger.kernel.org
Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Link: https://patch.msgid.link/20260224104203.42950-2-krzysztof.kozlowski@oss.qualcomm.com
Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>

authored by

Krzysztof Kozlowski and committed by
Krzysztof Kozlowski
a2be37ee f2e83070

+48 -52
+2 -2
drivers/clk/samsung/clk-acpm.c
··· 20 20 u32 id; 21 21 struct clk_hw hw; 22 22 unsigned int mbox_chan_id; 23 - const struct acpm_handle *handle; 23 + struct acpm_handle *handle; 24 24 }; 25 25 26 26 struct acpm_clk_variant { ··· 113 113 114 114 static int acpm_clk_probe(struct platform_device *pdev) 115 115 { 116 - const struct acpm_handle *acpm_handle; 116 + struct acpm_handle *acpm_handle; 117 117 struct clk_hw_onecell_data *clk_data; 118 118 struct clk_hw **hws; 119 119 struct device *dev = &pdev->dev;
+2 -2
drivers/firmware/samsung/exynos-acpm-dvfs.c
··· 43 43 cmd[3] = ktime_to_ms(ktime_get()); 44 44 } 45 45 46 - int acpm_dvfs_set_rate(const struct acpm_handle *handle, 46 + int acpm_dvfs_set_rate(struct acpm_handle *handle, 47 47 unsigned int acpm_chan_id, unsigned int clk_id, 48 48 unsigned long rate) 49 49 { ··· 63 63 cmd[3] = ktime_to_ms(ktime_get()); 64 64 } 65 65 66 - unsigned long acpm_dvfs_get_rate(const struct acpm_handle *handle, 66 + unsigned long acpm_dvfs_get_rate(struct acpm_handle *handle, 67 67 unsigned int acpm_chan_id, unsigned int clk_id) 68 68 { 69 69 struct acpm_xfer xfer;
+2 -2
drivers/firmware/samsung/exynos-acpm-dvfs.h
··· 11 11 12 12 struct acpm_handle; 13 13 14 - int acpm_dvfs_set_rate(const struct acpm_handle *handle, 14 + int acpm_dvfs_set_rate(struct acpm_handle *handle, 15 15 unsigned int acpm_chan_id, unsigned int id, 16 16 unsigned long rate); 17 - unsigned long acpm_dvfs_get_rate(const struct acpm_handle *handle, 17 + unsigned long acpm_dvfs_get_rate(struct acpm_handle *handle, 18 18 unsigned int acpm_chan_id, 19 19 unsigned int clk_id); 20 20
+5 -5
drivers/firmware/samsung/exynos-acpm-pmic.c
··· 77 77 cmd[3] = ktime_to_ms(ktime_get()); 78 78 } 79 79 80 - int acpm_pmic_read_reg(const struct acpm_handle *handle, 80 + int acpm_pmic_read_reg(struct acpm_handle *handle, 81 81 unsigned int acpm_chan_id, u8 type, u8 reg, u8 chan, 82 82 u8 *buf) 83 83 { ··· 107 107 FIELD_PREP(ACPM_PMIC_VALUE, count); 108 108 } 109 109 110 - int acpm_pmic_bulk_read(const struct acpm_handle *handle, 110 + int acpm_pmic_bulk_read(struct acpm_handle *handle, 111 111 unsigned int acpm_chan_id, u8 type, u8 reg, u8 chan, 112 112 u8 count, u8 *buf) 113 113 { ··· 150 150 cmd[3] = ktime_to_ms(ktime_get()); 151 151 } 152 152 153 - int acpm_pmic_write_reg(const struct acpm_handle *handle, 153 + int acpm_pmic_write_reg(struct acpm_handle *handle, 154 154 unsigned int acpm_chan_id, u8 type, u8 reg, u8 chan, 155 155 u8 value) 156 156 { ··· 187 187 } 188 188 } 189 189 190 - int acpm_pmic_bulk_write(const struct acpm_handle *handle, 190 + int acpm_pmic_bulk_write(struct acpm_handle *handle, 191 191 unsigned int acpm_chan_id, u8 type, u8 reg, u8 chan, 192 192 u8 count, const u8 *buf) 193 193 { ··· 220 220 cmd[3] = ktime_to_ms(ktime_get()); 221 221 } 222 222 223 - int acpm_pmic_update_reg(const struct acpm_handle *handle, 223 + int acpm_pmic_update_reg(struct acpm_handle *handle, 224 224 unsigned int acpm_chan_id, u8 type, u8 reg, u8 chan, 225 225 u8 value, u8 mask) 226 226 {
+5 -5
drivers/firmware/samsung/exynos-acpm-pmic.h
··· 11 11 12 12 struct acpm_handle; 13 13 14 - int acpm_pmic_read_reg(const struct acpm_handle *handle, 14 + int acpm_pmic_read_reg(struct acpm_handle *handle, 15 15 unsigned int acpm_chan_id, u8 type, u8 reg, u8 chan, 16 16 u8 *buf); 17 - int acpm_pmic_bulk_read(const struct acpm_handle *handle, 17 + int acpm_pmic_bulk_read(struct acpm_handle *handle, 18 18 unsigned int acpm_chan_id, u8 type, u8 reg, u8 chan, 19 19 u8 count, u8 *buf); 20 - int acpm_pmic_write_reg(const struct acpm_handle *handle, 20 + int acpm_pmic_write_reg(struct acpm_handle *handle, 21 21 unsigned int acpm_chan_id, u8 type, u8 reg, u8 chan, 22 22 u8 value); 23 - int acpm_pmic_bulk_write(const struct acpm_handle *handle, 23 + int acpm_pmic_bulk_write(struct acpm_handle *handle, 24 24 unsigned int acpm_chan_id, u8 type, u8 reg, u8 chan, 25 25 u8 count, const u8 *buf); 26 - int acpm_pmic_update_reg(const struct acpm_handle *handle, 26 + int acpm_pmic_update_reg(struct acpm_handle *handle, 27 27 unsigned int acpm_chan_id, u8 type, u8 reg, u8 chan, 28 28 u8 value, u8 mask); 29 29 #endif /* __EXYNOS_ACPM_PMIC_H__ */
+9 -7
drivers/firmware/samsung/exynos-acpm.c
··· 410 410 * 411 411 * Return: 0 on success, -errno otherwise. 412 412 */ 413 - int acpm_do_xfer(const struct acpm_handle *handle, const struct acpm_xfer *xfer) 413 + int acpm_do_xfer(struct acpm_handle *handle, const struct acpm_xfer *xfer) 414 414 { 415 415 struct acpm_info *acpm = handle_to_acpm_info(handle); 416 416 struct exynos_mbox_msg msg; ··· 674 674 * acpm_handle_put() - release the handle acquired by acpm_get_by_phandle. 675 675 * @handle: Handle acquired by acpm_get_by_phandle. 676 676 */ 677 - static void acpm_handle_put(const struct acpm_handle *handle) 677 + static void acpm_handle_put(struct acpm_handle *handle) 678 678 { 679 679 struct acpm_info *acpm = handle_to_acpm_info(handle); 680 680 struct device *dev = acpm->dev; ··· 700 700 * @np: ACPM device tree node. 701 701 * 702 702 * Return: pointer to handle on success, ERR_PTR(-errno) otherwise. 703 + * 704 + * Note: handle CANNOT be pointer to const 703 705 */ 704 - static const struct acpm_handle *acpm_get_by_node(struct device *dev, 705 - struct device_node *np) 706 + static struct acpm_handle *acpm_get_by_node(struct device *dev, 707 + struct device_node *np) 706 708 { 707 709 struct platform_device *pdev; 708 710 struct device_link *link; ··· 745 743 * 746 744 * Return: pointer to handle on success, ERR_PTR(-errno) otherwise. 747 745 */ 748 - const struct acpm_handle *devm_acpm_get_by_node(struct device *dev, 749 - struct device_node *np) 746 + struct acpm_handle *devm_acpm_get_by_node(struct device *dev, 747 + struct device_node *np) 750 748 { 751 - const struct acpm_handle **ptr, *handle; 749 + struct acpm_handle **ptr, *handle; 752 750 753 751 ptr = devres_alloc(devm_acpm_release, sizeof(*ptr), GFP_KERNEL); 754 752 if (!ptr)
+1 -1
drivers/firmware/samsung/exynos-acpm.h
··· 17 17 18 18 struct acpm_handle; 19 19 20 - int acpm_do_xfer(const struct acpm_handle *handle, 20 + int acpm_do_xfer(struct acpm_handle *handle, 21 21 const struct acpm_xfer *xfer); 22 22 23 23 #endif /* __EXYNOS_ACPM_H__ */
+5 -5
drivers/mfd/sec-acpm.c
··· 367 367 }; 368 368 369 369 struct sec_pmic_acpm_shared_bus_context { 370 - const struct acpm_handle *acpm; 370 + struct acpm_handle *acpm; 371 371 unsigned int acpm_chan_id; 372 372 u8 speedy_channel; 373 373 }; ··· 390 390 size_t count) 391 391 { 392 392 struct sec_pmic_acpm_bus_context *ctx = context; 393 - const struct acpm_handle *acpm = ctx->shared->acpm; 393 + struct acpm_handle *acpm = ctx->shared->acpm; 394 394 const struct acpm_pmic_ops *pmic_ops = &acpm->ops.pmic_ops; 395 395 size_t val_count = count - BITS_TO_BYTES(ACPM_ADDR_BITS); 396 396 const u8 *d = data; ··· 410 410 void *val_buf, size_t val_size) 411 411 { 412 412 struct sec_pmic_acpm_bus_context *ctx = context; 413 - const struct acpm_handle *acpm = ctx->shared->acpm; 413 + struct acpm_handle *acpm = ctx->shared->acpm; 414 414 const struct acpm_pmic_ops *pmic_ops = &acpm->ops.pmic_ops; 415 415 const u8 *r = reg_buf; 416 416 u8 reg; ··· 429 429 unsigned int val) 430 430 { 431 431 struct sec_pmic_acpm_bus_context *ctx = context; 432 - const struct acpm_handle *acpm = ctx->shared->acpm; 432 + struct acpm_handle *acpm = ctx->shared->acpm; 433 433 const struct acpm_pmic_ops *pmic_ops = &acpm->ops.pmic_ops; 434 434 435 435 return pmic_ops->update_reg(acpm, ctx->shared->acpm_chan_id, ctx->type, reg & 0xff, ··· 480 480 struct regmap *regmap_common, *regmap_pmic, *regmap; 481 481 const struct sec_pmic_acpm_platform_data *pdata; 482 482 struct sec_pmic_acpm_shared_bus_context *shared_ctx; 483 - const struct acpm_handle *acpm; 483 + struct acpm_handle *acpm; 484 484 struct device *dev = &pdev->dev; 485 485 int ret, irq; 486 486
+17 -23
include/linux/firmware/samsung/exynos-acpm-protocol.h
··· 14 14 struct device_node; 15 15 16 16 struct acpm_dvfs_ops { 17 - int (*set_rate)(const struct acpm_handle *handle, 18 - unsigned int acpm_chan_id, unsigned int clk_id, 19 - unsigned long rate); 20 - unsigned long (*get_rate)(const struct acpm_handle *handle, 17 + int (*set_rate)(struct acpm_handle *handle, unsigned int acpm_chan_id, 18 + unsigned int clk_id, unsigned long rate); 19 + unsigned long (*get_rate)(struct acpm_handle *handle, 21 20 unsigned int acpm_chan_id, 22 21 unsigned int clk_id); 23 22 }; 24 23 25 24 struct acpm_pmic_ops { 26 - int (*read_reg)(const struct acpm_handle *handle, 27 - unsigned int acpm_chan_id, u8 type, u8 reg, u8 chan, 28 - u8 *buf); 29 - int (*bulk_read)(const struct acpm_handle *handle, 30 - unsigned int acpm_chan_id, u8 type, u8 reg, u8 chan, 31 - u8 count, u8 *buf); 32 - int (*write_reg)(const struct acpm_handle *handle, 33 - unsigned int acpm_chan_id, u8 type, u8 reg, u8 chan, 34 - u8 value); 35 - int (*bulk_write)(const struct acpm_handle *handle, 36 - unsigned int acpm_chan_id, u8 type, u8 reg, u8 chan, 37 - u8 count, const u8 *buf); 38 - int (*update_reg)(const struct acpm_handle *handle, 39 - unsigned int acpm_chan_id, u8 type, u8 reg, u8 chan, 40 - u8 value, u8 mask); 25 + int (*read_reg)(struct acpm_handle *handle, unsigned int acpm_chan_id, 26 + u8 type, u8 reg, u8 chan, u8 *buf); 27 + int (*bulk_read)(struct acpm_handle *handle, unsigned int acpm_chan_id, 28 + u8 type, u8 reg, u8 chan, u8 count, u8 *buf); 29 + int (*write_reg)(struct acpm_handle *handle, unsigned int acpm_chan_id, 30 + u8 type, u8 reg, u8 chan, u8 value); 31 + int (*bulk_write)(struct acpm_handle *handle, unsigned int acpm_chan_id, 32 + u8 type, u8 reg, u8 chan, u8 count, const u8 *buf); 33 + int (*update_reg)(struct acpm_handle *handle, unsigned int acpm_chan_id, 34 + u8 type, u8 reg, u8 chan, u8 value, u8 mask); 41 35 }; 42 36 43 37 struct acpm_ops { ··· 50 56 struct device; 51 57 52 58 #if IS_ENABLED(CONFIG_EXYNOS_ACPM_PROTOCOL) 53 - const struct acpm_handle *devm_acpm_get_by_node(struct device *dev, 54 - struct device_node *np); 59 + struct acpm_handle *devm_acpm_get_by_node(struct device *dev, 60 + struct device_node *np); 55 61 #else 56 62 57 - static inline const struct acpm_handle *devm_acpm_get_by_node(struct device *dev, 58 - struct device_node *np) 63 + static inline struct acpm_handle *devm_acpm_get_by_node(struct device *dev, 64 + struct device_node *np) 59 65 { 60 66 return NULL; 61 67 }