In Commit a8f5738779a9 ("drm/panthor: Pass an iomem pointer to GPU
register access helpers"), the gpu register access helpers were changed
from taking a pointer to a struct panthor_device in their first
argument, to taking a void pointer.This can cause problems, as patches based on panthor before this change will still compile fine after it. struct panthor_device * implicitly casts to a void pointer, resulting in completely wrong semantics. Prevent this problem by wrapping the affected functions with macros that specifically check for and reject the struct panthor_device * type as the first argument. Signed-off-by: Nicolas Frattaroli <[email protected]> --- drivers/gpu/drm/panthor/panthor_device.h | 68 +++++++++++++++++++++++++------- 1 file changed, 53 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/panthor/panthor_device.h b/drivers/gpu/drm/panthor/panthor_device.h index 4e4607bca7cc..91e9f499bf69 100644 --- a/drivers/gpu/drm/panthor/panthor_device.h +++ b/drivers/gpu/drm/panthor/panthor_device.h @@ -630,49 +630,87 @@ static inline void panthor_ ## __name ## _irq_disable_events(struct panthor_irq extern struct workqueue_struct *panthor_cleanup_wq; -static inline void gpu_write(void __iomem *iomem, u32 reg, u32 data) +static inline void _gpu_write(void __iomem *iomem, u32 reg, u32 data) { writel(data, iomem + reg); } -static inline u32 gpu_read(void __iomem *iomem, u32 reg) +static inline u32 _gpu_read(void __iomem *iomem, u32 reg) { return readl(iomem + reg); } -static inline u32 gpu_read_relaxed(void __iomem *iomem, u32 reg) +static inline u32 _gpu_read_relaxed(void __iomem *iomem, u32 reg) { return readl_relaxed(iomem + reg); } -static inline void gpu_write64(void __iomem *iomem, u32 reg, u64 data) +/* + * The function signature of gpu_read/gpu_write/gpu_read_relaxed/... used to + * take a &struct panthor_device* as the first parameter. During the split of + * iomem ranges into individual sub-components, this was changed to take a + * void __iomem* instead. These wrappers exists Tto avoid situations wherein + * pre-refactor patches are applied in error, as they'd compile fine. That's + * because the old calling convention's first parameter implicitly casts to a + * void pointer. + */ + +#define gpu_write(iomem, reg, data) ({ \ + static_assert(!__same_type((iomem), struct panthor_device *)); \ + _gpu_write((iomem), (reg), (data)); }) + +#define gpu_read(iomem, reg) ({ \ + static_assert(!__same_type((iomem), struct panthor_device *)); \ + _gpu_read((iomem), (reg)); }) + +#define gpu_read_relaxed(iomem, reg) ({ \ + static_assert(!__same_type((iomem), struct panthor_device *)); \ + _gpu_read_relaxed((iomem), (reg)); }) + +static inline void _gpu_write64(void __iomem *iomem, u32 reg, u64 data) { - gpu_write(iomem, reg, lower_32_bits(data)); - gpu_write(iomem, reg + 4, upper_32_bits(data)); + _gpu_write(iomem, reg, lower_32_bits(data)); + _gpu_write(iomem, reg + 4, upper_32_bits(data)); } -static inline u64 gpu_read64(void __iomem *iomem, u32 reg) +#define gpu_write64(iomem, reg, data) ({ \ + static_assert(!__same_type((iomem), struct panthor_device *)); \ + _gpu_write64((iomem), (reg), (data)); }) + +static inline u64 _gpu_read64(void __iomem *iomem, u32 reg) { - return (gpu_read(iomem, reg) | ((u64)gpu_read(iomem, reg + 4) << 32)); + return (_gpu_read(iomem, reg) | ((u64)_gpu_read(iomem, reg + 4) << 32)); } -static inline u64 gpu_read64_relaxed(void __iomem *iomem, u32 reg) +#define gpu_read64(iomem, reg) ({ \ + static_assert(!__same_type((iomem), struct panthor_device *)); \ + _gpu_read64((iomem), (reg)); }) + +static inline u64 _gpu_read64_relaxed(void __iomem *iomem, u32 reg) { - return (gpu_read_relaxed(iomem, reg) | - ((u64)gpu_read_relaxed(iomem, reg + 4) << 32)); + return (_gpu_read_relaxed(iomem, reg) | + ((u64)_gpu_read_relaxed(iomem, reg + 4) << 32)); } -static inline u64 gpu_read64_counter(void __iomem *iomem, u32 reg) +#define gpu_read64_relaxed(iomem, reg) ({ \ + static_assert(!__same_type((iomem), struct panthor_device *)); \ + _gpu_read64_relaxed((iomem), (reg)); }) + +static inline u64 _gpu_read64_counter(void __iomem *iomem, u32 reg) { u32 lo, hi1, hi2; do { - hi1 = gpu_read(iomem, reg + 4); - lo = gpu_read(iomem, reg); - hi2 = gpu_read(iomem, reg + 4); + hi1 = _gpu_read(iomem, reg + 4); + lo = _gpu_read(iomem, reg); + hi2 = _gpu_read(iomem, reg + 4); } while (hi1 != hi2); return lo | ((u64)hi2 << 32); } +#define gpu_read64_counter(iomem, reg) ({ \ + static_assert(!__same_type((iomem), struct panthor_device *)); \ + _gpu_read64_counter((iomem), (reg)); }) + #define gpu_read_poll_timeout(iomem, reg, val, cond, delay_us, timeout_us) \ read_poll_timeout(gpu_read, val, cond, delay_us, timeout_us, false, \ iomem, reg) --- base-commit: 3c253a3bef01b39d4640cfe3dfd38d8d5557ae0c change-id: 20260508-panthor-gpu-read-type-7ac3fffd124c Best regards, -- Nicolas Frattaroli <[email protected]>
