Commit d745a845 authored by Henry Ptasinski's avatar Henry Ptasinski Committed by Greg Kroah-Hartman

staging: brcm80211: Fix handling of firmware and inits on big-endian platforms

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: default avatarHenry Ptasinski <henryp@broadcom.com>
Reviewed-by: default avatarArend van Spriel <arend@broadcom.com>
Reviewed-by: default avatarRoland Vossen <rvossen@broadcom.com>
Tested-by: default avatarJonas Gorski <jonas.gorski@gmail.com>
Signed-off-by: default avatarArend van Spriel <arend@broadcom.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent ba1fff7f
...@@ -1722,15 +1722,17 @@ int brcms_ucode_init_buf(struct brcms_info *wl, void **pbuf, u32 idx) ...@@ -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; hdr = (struct firmware_hdr *)wl->fw.fw_hdr[i]->data;
for (entry = 0; entry < wl->fw.hdr_num_entries[i]; for (entry = 0; entry < wl->fw.hdr_num_entries[i];
entry++, hdr++) { entry++, hdr++) {
if (hdr->idx == idx) { u32 len = le32_to_cpu(hdr->len);
pdata = wl->fw.fw_bin[i]->data + hdr->offset; if (le32_to_cpu(hdr->idx) == idx) {
*pbuf = kmalloc(hdr->len, GFP_ATOMIC); pdata = wl->fw.fw_bin[i]->data +
le32_to_cpu(hdr->offset);
*pbuf = kmalloc(len, GFP_ATOMIC);
if (*pbuf == NULL) { if (*pbuf == NULL) {
wiphy_err(wl->wiphy, "fail to alloc %d" wiphy_err(wl->wiphy, "fail to alloc %d"
" bytes\n", hdr->len); " bytes\n", len);
goto fail; goto fail;
} }
memcpy(*pbuf, pdata, hdr->len); memcpy(*pbuf, pdata, len);
return 0; return 0;
} }
} }
...@@ -1755,14 +1757,15 @@ int brcms_ucode_init_uint(struct brcms_info *wl, u32 *data, u32 idx) ...@@ -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; hdr = (struct firmware_hdr *)wl->fw.fw_hdr[i]->data;
for (entry = 0; entry < wl->fw.hdr_num_entries[i]; for (entry = 0; entry < wl->fw.hdr_num_entries[i];
entry++, hdr++) { entry++, hdr++) {
if (hdr->idx == idx) { if (le32_to_cpu(hdr->idx) == idx) {
pdata = wl->fw.fw_bin[i]->data + hdr->offset; pdata = wl->fw.fw_bin[i]->data +
if (hdr->len != 4) { le32_to_cpu(hdr->offset);
if (le32_to_cpu(hdr->len) != 4) {
wiphy_err(wl->wiphy, wiphy_err(wl->wiphy,
"ERROR: fw hdr len\n"); "ERROR: fw hdr len\n");
return -ENOMSG; return -ENOMSG;
} }
*data = *((u32 *) pdata); *data = le32_to_cpu(*((u32 *) pdata));
return 0; return 0;
} }
} }
...@@ -1868,7 +1871,8 @@ int brcms_check_firmwares(struct brcms_info *wl) ...@@ -1868,7 +1871,8 @@ int brcms_check_firmwares(struct brcms_info *wl)
ucode_hdr = (struct firmware_hdr *)fw_hdr->data; ucode_hdr = (struct firmware_hdr *)fw_hdr->data;
for (entry = 0; entry < wl->fw.hdr_num_entries[i] && for (entry = 0; entry < wl->fw.hdr_num_entries[i] &&
!rc; entry++, ucode_hdr++) { !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) { fw->size) {
wiphy_err(wl->wiphy, wiphy_err(wl->wiphy,
"%s: conflicting bin/hdr\n", "%s: conflicting bin/hdr\n",
......
...@@ -2033,7 +2033,8 @@ static void brcms_ucode_write(struct brcms_hardware *wlc_hw, const u32 ucode[], ...@@ -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)); W_REG(&regs->objaddr, (OBJADDR_AUTO_INC | OBJADDR_UCM_SEL));
(void)R_REG(&regs->objaddr); (void)R_REG(&regs->objaddr);
for (i = 0; i < count; i++) 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, 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, ...@@ -2041,18 +2042,24 @@ static void brcms_c_write_inits(struct brcms_hardware *wlc_hw,
{ {
int i; int i;
u8 *base; u8 *base;
u8 *addr;
u16 size;
u32 value;
BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
base = (u8 *)wlc_hw->regs; base = (u8 *)wlc_hw->regs;
for (i = 0; inits[i].addr != 0xffff; i++) { for (i = 0; inits[i].addr != 0xffff; i++) {
if (inits[i].size == 2) size = le16_to_cpu(inits[i].size);
W_REG((u16 *)(base + inits[i].addr), addr = base + le16_to_cpu(inits[i].addr);
inits[i].value); value = le32_to_cpu(inits[i].value);
else if (inits[i].size == 4) if (size == 2)
W_REG((u32 *)(base + inits[i].addr), W_REG((u16 *)addr, value);
inits[i].value); else if (size == 4)
W_REG((u32 *)addr, value);
else
break;
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment