staging: brcm80211: Fix handling of firmware and inits on big-endian platforms
authorHenry Ptasinski <henryp@broadcom.com>
Mon, 15 Aug 2011 13:34:23 +0000 (15:34 +0200)
committerGreg Kroah-Hartman <gregkh@suse.de>
Tue, 23 Aug 2011 20:08:06 +0000 (13:08 -0700)
The firmware files are encoded as little-endian.  Do the appropriate swapping
for big-endian platforms.

Tested on Mac G5 PPC and BCM63281.

Signed-off-by: Henry Ptasinski <henryp@broadcom.com>
Reviewed-by: Arend van Spriel <arend@broadcom.com>
Reviewed-by: Roland Vossen <rvossen@broadcom.com>
Tested-by: Jonas Gorski <jonas.gorski@gmail.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/staging/brcm80211/brcmsmac/mac80211_if.c
drivers/staging/brcm80211/brcmsmac/main.c

index e465749..7179edd 100644 (file)
@@ -1722,15 +1722,17 @@ int brcms_ucode_init_buf(struct brcms_info *wl, void **pbuf, u32 idx)
                hdr = (struct firmware_hdr *)wl->fw.fw_hdr[i]->data;
                for (entry = 0; entry < wl->fw.hdr_num_entries[i];
                     entry++, hdr++) {
-                       if (hdr->idx == idx) {
-                               pdata = wl->fw.fw_bin[i]->data + hdr->offset;
-                               *pbuf = kmalloc(hdr->len, GFP_ATOMIC);
+                       u32 len = le32_to_cpu(hdr->len);
+                       if (le32_to_cpu(hdr->idx) == idx) {
+                               pdata = wl->fw.fw_bin[i]->data +
+                                       le32_to_cpu(hdr->offset);
+                               *pbuf = kmalloc(len, GFP_ATOMIC);
                                if (*pbuf == NULL) {
                                        wiphy_err(wl->wiphy, "fail to alloc %d"
-                                                 " bytes\n", hdr->len);
+                                                 " bytes\n", len);
                                        goto fail;
                                }
-                               memcpy(*pbuf, pdata, hdr->len);
+                               memcpy(*pbuf, pdata, len);
                                return 0;
                        }
                }
@@ -1755,14 +1757,15 @@ int brcms_ucode_init_uint(struct brcms_info *wl, u32 *data, u32 idx)
                hdr = (struct firmware_hdr *)wl->fw.fw_hdr[i]->data;
                for (entry = 0; entry < wl->fw.hdr_num_entries[i];
                     entry++, hdr++) {
-                       if (hdr->idx == idx) {
-                               pdata = wl->fw.fw_bin[i]->data + hdr->offset;
-                               if (hdr->len != 4) {
+                       if (le32_to_cpu(hdr->idx) == idx) {
+                               pdata = wl->fw.fw_bin[i]->data +
+                                       le32_to_cpu(hdr->offset);
+                               if (le32_to_cpu(hdr->len) != 4) {
                                        wiphy_err(wl->wiphy,
                                                  "ERROR: fw hdr len\n");
                                        return -ENOMSG;
                                }
-                               *data = *((u32 *) pdata);
+                               *data = le32_to_cpu(*((u32 *) pdata));
                                return 0;
                        }
                }
@@ -1868,7 +1871,8 @@ int brcms_check_firmwares(struct brcms_info *wl)
                        ucode_hdr = (struct firmware_hdr *)fw_hdr->data;
                        for (entry = 0; entry < wl->fw.hdr_num_entries[i] &&
                             !rc; entry++, ucode_hdr++) {
-                               if (ucode_hdr->offset + ucode_hdr->len >
+                               if (le32_to_cpu(ucode_hdr->offset) +
+                                   le32_to_cpu(ucode_hdr->len) >
                                    fw->size) {
                                        wiphy_err(wl->wiphy,
                                                  "%s: conflicting bin/hdr\n",
index d6837d3..c625c25 100644 (file)
@@ -2033,7 +2033,8 @@ static void brcms_ucode_write(struct brcms_hardware *wlc_hw, const u32 ucode[],
        W_REG(&regs->objaddr, (OBJADDR_AUTO_INC | OBJADDR_UCM_SEL));
        (void)R_REG(&regs->objaddr);
        for (i = 0; i < count; i++)
-               W_REG(&regs->objdata, ucode[i]);
+               W_REG(&regs->objdata, le32_to_cpu(ucode[i]));
+
 }
 
 static void brcms_c_write_inits(struct brcms_hardware *wlc_hw,
@@ -2041,18 +2042,24 @@ static void brcms_c_write_inits(struct brcms_hardware *wlc_hw,
 {
        int i;
        u8 *base;
+       u8 *addr;
+       u16 size;
+       u32 value;
 
        BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
 
        base = (u8 *)wlc_hw->regs;
 
        for (i = 0; inits[i].addr != 0xffff; i++) {
-               if (inits[i].size == 2)
-                       W_REG((u16 *)(base + inits[i].addr),
-                             inits[i].value);
-               else if (inits[i].size == 4)
-                       W_REG((u32 *)(base + inits[i].addr),
-                             inits[i].value);
+               size = le16_to_cpu(inits[i].size);
+               addr = base + le16_to_cpu(inits[i].addr);
+               value = le32_to_cpu(inits[i].value);
+               if (size == 2)
+                       W_REG((u16 *)addr, value);
+               else if (size == 4)
+                       W_REG((u32 *)addr, value);
+               else
+                       break;
        }
 }