usb: do explicit unaligned accesses
authorLucas Stach <dev@lynxeye.de>
Thu, 6 Sep 2012 06:00:13 +0000 (08:00 +0200)
committerChanho Park <chanho61.park@samsung.com>
Fri, 24 Jul 2015 07:29:54 +0000 (16:29 +0900)
usb_hub_descriptor has to be packed as it's used for
communication with the device. Member wHubCharacteristics
violates the natural alignment rules.

Use explicit unaligned access functions for this member.
Fixes ARMv7 traping while using USB.

v2: fix typo found by Thomas Langer

v3: rebased on top of u-boot-usb/master

Signed-off-by: Lucas Stach <dev@lynxeye.de>
common/usb_hub.c
drivers/usb/host/ehci-hcd.c

index 53d939c3abed300c9f2d75a2e9bd9ba4fbf1cd9b..e4a120120dc23d068686d0e69e6d8248f9b35308 100644 (file)
@@ -43,6 +43,7 @@
 #include <common.h>
 #include <command.h>
 #include <asm/processor.h>
+#include <asm/unaligned.h>
 #include <linux/ctype.h>
 #include <asm/byteorder.h>
 #include <asm/unaligned.h>
@@ -269,6 +270,7 @@ static int usb_hub_configure(struct usb_device *dev)
        int i;
        ALLOC_CACHE_ALIGN_BUFFER(unsigned char, buffer, USB_BUFSIZ);
        unsigned char *bitmap;
+       short hubCharacteristics;
        struct usb_hub_descriptor *descriptor;
        struct usb_hub_device *hub;
 #ifdef USB_HUB_DEBUG
@@ -304,8 +306,9 @@ static int usb_hub_configure(struct usb_device *dev)
        }
        memcpy((unsigned char *)&hub->desc, buffer, descriptor->bLength);
        /* adjust 16bit values */
-       hub->desc.wHubCharacteristics =
-                               le16_to_cpu(descriptor->wHubCharacteristics);
+       put_unaligned(le16_to_cpu(get_unaligned(
+                       &descriptor->wHubCharacteristics)),
+                       &hub->desc.wHubCharacteristics);
        /* set the bitmap */
        bitmap = (unsigned char *)&hub->desc.DeviceRemovable[0];
        /* devices not removable by default */
@@ -322,7 +325,8 @@ static int usb_hub_configure(struct usb_device *dev)
        dev->maxchild = descriptor->bNbrPorts;
        USB_HUB_PRINTF("%d ports detected\n", dev->maxchild);
 
-       switch (hub->desc.wHubCharacteristics & HUB_CHAR_LPSM) {
+       hubCharacteristics = get_unaligned(&hub->desc.wHubCharacteristics);
+       switch (hubCharacteristics & HUB_CHAR_LPSM) {
        case 0x00:
                USB_HUB_PRINTF("ganged power switching\n");
                break;
@@ -335,12 +339,12 @@ static int usb_hub_configure(struct usb_device *dev)
                break;
        }
 
-       if (hub->desc.wHubCharacteristics & HUB_CHAR_COMPOUND)
+       if (hubCharacteristics & HUB_CHAR_COMPOUND)
                USB_HUB_PRINTF("part of a compound device\n");
        else
                USB_HUB_PRINTF("standalone hub\n");
 
-       switch (hub->desc.wHubCharacteristics & HUB_CHAR_OCPM) {
+       switch (hubCharacteristics & HUB_CHAR_OCPM) {
        case 0x00:
                USB_HUB_PRINTF("global over-current protection\n");
                break;
index e8435e54cb63952377abfd7b6d0d180cff35667b..5d8714e688a38a4942f8f94868e17650c501ec9e 100644 (file)
@@ -22,6 +22,7 @@
  */
 #include <common.h>
 #include <asm/byteorder.h>
+#include <asm/unaligned.h>
 #include <usb.h>
 #include <asm/io.h>
 #include <malloc.h>
@@ -866,10 +867,12 @@ int usb_lowlevel_init(int index, void **controller)
        printf("Register %x NbrPorts %d\n", reg, descriptor.hub.bNbrPorts);
        /* Port Indicators */
        if (HCS_INDICATOR(reg))
-               descriptor.hub.wHubCharacteristics |= 0x80;
+               put_unaligned(get_unaligned(&descriptor.hub.wHubCharacteristics)
+                               | 0x80, &descriptor.hub.wHubCharacteristics);
        /* Port Power Control */
        if (HCS_PPC(reg))
-               descriptor.hub.wHubCharacteristics |= 0x01;
+               put_unaligned(get_unaligned(&descriptor.hub.wHubCharacteristics)
+                               | 0x01, &descriptor.hub.wHubCharacteristics);
 
        /* Start the host controller. */
        cmd = ehci_readl(&hcor->or_usbcmd);