Thread (2 messages) flat view 2 messages, 2 authors, 2018-03-12
STALE3116d

[PATCH 1/2] video: udlfb: Fix unaligned access

From: Ladislav Michl <hidden>
Date: 2018-02-06 20:08:38
Subsystem: displaylink usb 2.0 framebuffer driver (udlfb), framebuffer layer, the rest · Maintainers: Bernie Thompson, Helge Deller, Linus Torvalds

Driver generates lots of alignment trap exceptions on ARM.
Fix that by replacing typecasting of odd addresses with
byte shifting and remove uneccessary typecasting.

Signed-off-by: Ladislav Michl <redacted>
---
 Here's what happens on at91sam9g20 few minutes after boot:
 $ cat /proc/cpu/alignment
 User:           0
 System:         10747836 (dlfb_render_hline+0x22c/0x2f0 [udlfb])
 Skipped:        0
 Half:           10747971
 Word:           159
 DWord:          0
 Multi:          0
 Each hline transfer causes dozens alignment exceptions and
 few are in dlfb_parse_vendor_descriptor function.

 drivers/video/fbdev/udlfb.c | 23 ++++++++++++-----------
 1 file changed, 12 insertions(+), 11 deletions(-)
diff --git a/drivers/video/fbdev/udlfb.c b/drivers/video/fbdev/udlfb.c
index 452a4207ac1b..45081297efa5 100644
--- a/drivers/video/fbdev/udlfb.c
+++ b/drivers/video/fbdev/udlfb.c
@@ -441,9 +441,9 @@ static void dlfb_compress_hline(
 
 		*cmd++ = 0xAF;
 		*cmd++ = 0x6B;
-		*cmd++ = (uint8_t) ((dev_addr >> 16) & 0xFF);
-		*cmd++ = (uint8_t) ((dev_addr >> 8) & 0xFF);
-		*cmd++ = (uint8_t) ((dev_addr) & 0xFF);
+		*cmd++ = dev_addr >> 16;
+		*cmd++ = dev_addr >> 8;
+		*cmd++ = dev_addr;
 
 		cmd_pixels_count_byte = cmd++; /*  we'll know this later */
 		cmd_pixel_start = pixel;
@@ -460,8 +460,8 @@ static void dlfb_compress_hline(
 		while (pixel < cmd_pixel_end) {
 			const uint16_t * const repeating_pixel = pixel;
 
-			*(uint16_t *)cmd = cpu_to_be16p(pixel);
-			cmd += 2;
+			*cmd++ = *pixel >> 8;
+			*cmd++ = *pixel;
 			pixel++;
 
 			if (unlikely((pixel < cmd_pixel_end) &&
@@ -1531,15 +1531,16 @@ static int dlfb_parse_vendor_descriptor(struct dlfb_data *dlfb,
 			u8 length;
 			u16 key;
 
-			key = le16_to_cpu(*((u16 *) desc));
-			desc += sizeof(u16);
-			length = *desc;
-			desc++;
+			key = *desc++;
+			key |= (u16)*desc++ << 8;
+			length = *desc++;
 
 			switch (key) {
 			case 0x0200: { /* max_area */
-				u32 max_area;
-				max_area = le32_to_cpu(*((u32 *)desc));
+				u32 max_area = *desc++;
+				max_area |= (u32)*desc++ << 8;
+				max_area |= (u32)*desc++ << 16;
+				max_area |= (u32)*desc++ << 24;
 				dev_warn(&intf->dev,
 					 "DL chip limited to %d pixel modes\n",
 					 max_area);
-- 
2.16.1
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help