Skip to content

Commit 47f1556

Browse files
committed
drm: fix EDID struct for old ARM OABI format
When building the kernel for arm with the "-mabi=apcs-gnu" option, gcc will force alignment of all structures and unions to a word boundary (see also STRUCTURE_SIZE_BOUNDARY and the "-mstructure-size-boundary=XX" option if you're a gcc person), even when the members of said structures do not want or need said alignment. This completely messes up the structure alignment of 'struct edid' on those targets, because even though all the embedded structures are marked with "__attribute__((packed))", the unions that contain them are not. This was exposed by commit f1e4c91 ("drm/edid: add EDID block count and size helpers"), but the bug is pre-existing. That commit just made the structure layout problem cause a build failure due to the addition of the BUILD_BUG_ON(sizeof(*edid) != EDID_LENGTH); sanity check in drivers/gpu/drm/drm_edid.c:edid_block_data(). This legacy union alignment should probably not be used in the first place, but we can fix the layout by adding the packed attribute to the union entries even when each member is already packed and it shouldn't matter in a sane build environment. You can see this issue with a trivial test program: union { struct { char c[5]; }; struct { char d; unsigned e; } __attribute__((packed)); } a = { "1234" }; where building this with a normal "gcc -S" will result in the expected 5-byte size of said union: .type a, @object .size a, 5 but with an ARM compiler and the old ABI: arm-linux-gnu-gcc -mabi=apcs-gnu -mfloat-abi=soft -S t.c you get .type a, %object .size a, 8 instead, because even though each member of the union is packed, the union itself still gets aligned. This was reported by Sudip for the spear3xx_defconfig target. Link: https://lore.kernel.org/lkml/YpCUzStDnSgQLNFN@debian/ Reported-by: Sudip Mukherjee <sudipm.mukherjee@gmail.com> Acked-by: Arnd Bergmann <arnd@arndb.de> Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Cc: Maxime Ripard <mripard@kernel.org> Cc: Thomas Zimmermann <tzimmermann@suse.de> Cc: David Airlie <airlied@linux.ie> Cc: Daniel Vetter <daniel@ffwll.ch> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
1 parent f56dbdd commit 47f1556

1 file changed

Lines changed: 3 additions & 3 deletions

File tree

include/drm/drm_edid.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ struct detailed_data_monitor_range {
121121
u8 supported_scalings;
122122
u8 preferred_refresh;
123123
} __attribute__((packed)) cvt;
124-
} formula;
124+
} __attribute__((packed)) formula;
125125
} __attribute__((packed));
126126

127127
struct detailed_data_wpindex {
@@ -154,7 +154,7 @@ struct detailed_non_pixel {
154154
struct detailed_data_wpindex color;
155155
struct std_timing timings[6];
156156
struct cvt_timing cvt[4];
157-
} data;
157+
} __attribute__((packed)) data;
158158
} __attribute__((packed));
159159

160160
#define EDID_DETAIL_EST_TIMINGS 0xf7
@@ -172,7 +172,7 @@ struct detailed_timing {
172172
union {
173173
struct detailed_pixel_timing pixel_data;
174174
struct detailed_non_pixel other_data;
175-
} data;
175+
} __attribute__((packed)) data;
176176
} __attribute__((packed));
177177

178178
#define DRM_EDID_INPUT_SERRATION_VSYNC (1 << 0)

0 commit comments

Comments
 (0)