Skip to content

Commit 3d8623e

Browse files
Shahed Shaikhdavem330
authored andcommitted
qlcnic: Fix endianess issue in firmware load from file operation
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 <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent d874df5 commit 3d8623e

File tree

1 file changed

+25
-10
lines changed

1 file changed

+25
-10
lines changed

drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1378,47 +1378,62 @@ static int qlcnic_83xx_copy_fw_file(struct qlcnic_adapter *adapter)
13781378
{
13791379
struct qlc_83xx_fw_info *fw_info = adapter->ahw->fw_info;
13801380
const struct firmware *fw = fw_info->fw;
1381-
u32 dest, *p_cache;
1381+
u32 dest, *p_cache, *temp;
13821382
int i, ret = -EIO;
1383+
__le32 *temp_le;
13831384
u8 data[16];
13841385
size_t size;
13851386
u64 addr;
13861387

1388+
temp = kzalloc(fw->size, GFP_KERNEL);
1389+
if (!temp) {
1390+
release_firmware(fw);
1391+
fw_info->fw = NULL;
1392+
return -ENOMEM;
1393+
}
1394+
1395+
temp_le = (__le32 *)fw->data;
1396+
1397+
/* FW image in file is in little endian, swap the data to nullify
1398+
* the effect of writel() operation on big endian platform.
1399+
*/
1400+
for (i = 0; i < fw->size / sizeof(u32); i++)
1401+
temp[i] = __le32_to_cpu(temp_le[i]);
1402+
13871403
dest = QLCRDX(adapter->ahw, QLCNIC_FW_IMAGE_ADDR);
13881404
size = (fw->size & ~0xF);
1389-
p_cache = (u32 *)fw->data;
1405+
p_cache = temp;
13901406
addr = (u64)dest;
13911407

13921408
ret = qlcnic_ms_mem_write128(adapter, addr,
13931409
p_cache, size / 16);
13941410
if (ret) {
13951411
dev_err(&adapter->pdev->dev, "MS memory write failed\n");
1396-
release_firmware(fw);
1397-
fw_info->fw = NULL;
1398-
return -EIO;
1412+
goto exit;
13991413
}
14001414

14011415
/* alignment check */
14021416
if (fw->size & 0xF) {
14031417
addr = dest + size;
14041418
for (i = 0; i < (fw->size & 0xF); i++)
1405-
data[i] = fw->data[size + i];
1419+
data[i] = temp[size + i];
14061420
for (; i < 16; i++)
14071421
data[i] = 0;
14081422
ret = qlcnic_ms_mem_write128(adapter, addr,
14091423
(u32 *)data, 1);
14101424
if (ret) {
14111425
dev_err(&adapter->pdev->dev,
14121426
"MS memory write failed\n");
1413-
release_firmware(fw);
1414-
fw_info->fw = NULL;
1415-
return -EIO;
1427+
goto exit;
14161428
}
14171429
}
1430+
1431+
exit:
14181432
release_firmware(fw);
14191433
fw_info->fw = NULL;
1434+
kfree(temp);
14201435

1421-
return 0;
1436+
return ret;
14221437
}
14231438

14241439
static void qlcnic_83xx_dump_pause_control_regs(struct qlcnic_adapter *adapter)

0 commit comments

Comments
 (0)