Skip to content

Commit

Permalink
qlcnic: Fix endianess issue in firmware load from file operation
Browse files Browse the repository at this point in the history
Firmware binary file is in little endian. On big-endian architecture, while
writing this binary FW file to adapters memory, writel() swaps the data resulting into
corruption of FW image. So, swap the data before writing into adapters memory.

Signed-off-by: Shahed Shaikh <shahed.shaikh@qlogic.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Shahed Shaikh authored and David S. Miller committed Aug 22, 2014
1 parent d874df5 commit 3d8623e
Showing 1 changed file with 25 additions and 10 deletions.
35 changes: 25 additions & 10 deletions drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -1378,47 +1378,62 @@ static int qlcnic_83xx_copy_fw_file(struct qlcnic_adapter *adapter)
{
struct qlc_83xx_fw_info *fw_info = adapter->ahw->fw_info;
const struct firmware *fw = fw_info->fw;
u32 dest, *p_cache;
u32 dest, *p_cache, *temp;
int i, ret = -EIO;
__le32 *temp_le;
u8 data[16];
size_t size;
u64 addr;

temp = kzalloc(fw->size, GFP_KERNEL);
if (!temp) {
release_firmware(fw);
fw_info->fw = NULL;
return -ENOMEM;
}

temp_le = (__le32 *)fw->data;

/* FW image in file is in little endian, swap the data to nullify
* the effect of writel() operation on big endian platform.
*/
for (i = 0; i < fw->size / sizeof(u32); i++)
temp[i] = __le32_to_cpu(temp_le[i]);

dest = QLCRDX(adapter->ahw, QLCNIC_FW_IMAGE_ADDR);
size = (fw->size & ~0xF);
p_cache = (u32 *)fw->data;
p_cache = temp;
addr = (u64)dest;

ret = qlcnic_ms_mem_write128(adapter, addr,
p_cache, size / 16);
if (ret) {
dev_err(&adapter->pdev->dev, "MS memory write failed\n");
release_firmware(fw);
fw_info->fw = NULL;
return -EIO;
goto exit;
}

/* alignment check */
if (fw->size & 0xF) {
addr = dest + size;
for (i = 0; i < (fw->size & 0xF); i++)
data[i] = fw->data[size + i];
data[i] = temp[size + i];
for (; i < 16; i++)
data[i] = 0;
ret = qlcnic_ms_mem_write128(adapter, addr,
(u32 *)data, 1);
if (ret) {
dev_err(&adapter->pdev->dev,
"MS memory write failed\n");
release_firmware(fw);
fw_info->fw = NULL;
return -EIO;
goto exit;
}
}

exit:
release_firmware(fw);
fw_info->fw = NULL;
kfree(temp);

return 0;
return ret;
}

static void qlcnic_83xx_dump_pause_control_regs(struct qlcnic_adapter *adapter)
Expand Down

0 comments on commit 3d8623e

Please sign in to comment.