cxgb4: fix endianness when flashing boot image

[ Upstream commit 42a2039753a7f758ba5c85cb199fcf10dc2111eb ]

Boot images are copied to memory and updated with current underlying
device ID before flashing them to adapter. Ensure the updated images
are always flashed in Big Endian to allow the firmware to read the
new images during boot properly.

Fixes: 550883558f ("cxgb4: add support to flash boot image")
Signed-off-by: Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
Rahul Lakkireddy
2021-06-11 12:17:45 +05:30
committed by Greg Kroah-Hartman
parent 5bf940fe91
commit 3d60457d74

View File

@@ -3067,16 +3067,19 @@ int t4_read_flash(struct adapter *adapter, unsigned int addr,
* @addr: the start address to write * @addr: the start address to write
* @n: length of data to write in bytes * @n: length of data to write in bytes
* @data: the data to write * @data: the data to write
* @byte_oriented: whether to store data as bytes or as words
* *
* Writes up to a page of data (256 bytes) to the serial flash starting * Writes up to a page of data (256 bytes) to the serial flash starting
* at the given address. All the data must be written to the same page. * at the given address. All the data must be written to the same page.
* If @byte_oriented is set the write data is stored as byte stream
* (i.e. matches what on disk), otherwise in big-endian.
*/ */
static int t4_write_flash(struct adapter *adapter, unsigned int addr, static int t4_write_flash(struct adapter *adapter, unsigned int addr,
unsigned int n, const u8 *data) unsigned int n, const u8 *data, bool byte_oriented)
{ {
int ret;
u32 buf[64];
unsigned int i, c, left, val, offset = addr & 0xff; unsigned int i, c, left, val, offset = addr & 0xff;
u32 buf[64];
int ret;
if (addr >= adapter->params.sf_size || offset + n > SF_PAGE_SIZE) if (addr >= adapter->params.sf_size || offset + n > SF_PAGE_SIZE)
return -EINVAL; return -EINVAL;
@@ -3087,10 +3090,14 @@ static int t4_write_flash(struct adapter *adapter, unsigned int addr,
(ret = sf1_write(adapter, 4, 1, 1, val)) != 0) (ret = sf1_write(adapter, 4, 1, 1, val)) != 0)
goto unlock; goto unlock;
for (left = n; left; left -= c) { for (left = n; left; left -= c, data += c) {
c = min(left, 4U); c = min(left, 4U);
for (val = 0, i = 0; i < c; ++i) for (val = 0, i = 0; i < c; ++i) {
val = (val << 8) + *data++; if (byte_oriented)
val = (val << 8) + data[i];
else
val = (val << 8) + data[c - i - 1];
}
ret = sf1_write(adapter, c, c != left, 1, val); ret = sf1_write(adapter, c, c != left, 1, val);
if (ret) if (ret)
@@ -3103,7 +3110,8 @@ static int t4_write_flash(struct adapter *adapter, unsigned int addr,
t4_write_reg(adapter, SF_OP_A, 0); /* unlock SF */ t4_write_reg(adapter, SF_OP_A, 0); /* unlock SF */
/* Read the page to verify the write succeeded */ /* Read the page to verify the write succeeded */
ret = t4_read_flash(adapter, addr & ~0xff, ARRAY_SIZE(buf), buf, 1); ret = t4_read_flash(adapter, addr & ~0xff, ARRAY_SIZE(buf), buf,
byte_oriented);
if (ret) if (ret)
return ret; return ret;
@@ -3699,7 +3707,7 @@ int t4_load_fw(struct adapter *adap, const u8 *fw_data, unsigned int size)
*/ */
memcpy(first_page, fw_data, SF_PAGE_SIZE); memcpy(first_page, fw_data, SF_PAGE_SIZE);
((struct fw_hdr *)first_page)->fw_ver = cpu_to_be32(0xffffffff); ((struct fw_hdr *)first_page)->fw_ver = cpu_to_be32(0xffffffff);
ret = t4_write_flash(adap, fw_start, SF_PAGE_SIZE, first_page); ret = t4_write_flash(adap, fw_start, SF_PAGE_SIZE, first_page, true);
if (ret) if (ret)
goto out; goto out;
@@ -3707,14 +3715,14 @@ int t4_load_fw(struct adapter *adap, const u8 *fw_data, unsigned int size)
for (size -= SF_PAGE_SIZE; size; size -= SF_PAGE_SIZE) { for (size -= SF_PAGE_SIZE; size; size -= SF_PAGE_SIZE) {
addr += SF_PAGE_SIZE; addr += SF_PAGE_SIZE;
fw_data += SF_PAGE_SIZE; fw_data += SF_PAGE_SIZE;
ret = t4_write_flash(adap, addr, SF_PAGE_SIZE, fw_data); ret = t4_write_flash(adap, addr, SF_PAGE_SIZE, fw_data, true);
if (ret) if (ret)
goto out; goto out;
} }
ret = t4_write_flash(adap, ret = t4_write_flash(adap, fw_start + offsetof(struct fw_hdr, fw_ver),
fw_start + offsetof(struct fw_hdr, fw_ver), sizeof(hdr->fw_ver), (const u8 *)&hdr->fw_ver,
sizeof(hdr->fw_ver), (const u8 *)&hdr->fw_ver); true);
out: out:
if (ret) if (ret)
dev_err(adap->pdev_dev, "firmware download failed, error %d\n", dev_err(adap->pdev_dev, "firmware download failed, error %d\n",
@@ -10215,7 +10223,7 @@ int t4_load_cfg(struct adapter *adap, const u8 *cfg_data, unsigned int size)
n = size - i; n = size - i;
else else
n = SF_PAGE_SIZE; n = SF_PAGE_SIZE;
ret = t4_write_flash(adap, addr, n, cfg_data); ret = t4_write_flash(adap, addr, n, cfg_data, true);
if (ret) if (ret)
goto out; goto out;
@@ -10684,13 +10692,14 @@ int t4_load_boot(struct adapter *adap, u8 *boot_data,
for (size -= SF_PAGE_SIZE; size; size -= SF_PAGE_SIZE) { for (size -= SF_PAGE_SIZE; size; size -= SF_PAGE_SIZE) {
addr += SF_PAGE_SIZE; addr += SF_PAGE_SIZE;
boot_data += SF_PAGE_SIZE; boot_data += SF_PAGE_SIZE;
ret = t4_write_flash(adap, addr, SF_PAGE_SIZE, boot_data); ret = t4_write_flash(adap, addr, SF_PAGE_SIZE, boot_data,
false);
if (ret) if (ret)
goto out; goto out;
} }
ret = t4_write_flash(adap, boot_sector, SF_PAGE_SIZE, ret = t4_write_flash(adap, boot_sector, SF_PAGE_SIZE,
(const u8 *)header); (const u8 *)header, false);
out: out:
if (ret) if (ret)
@@ -10765,7 +10774,7 @@ int t4_load_bootcfg(struct adapter *adap, const u8 *cfg_data, unsigned int size)
for (i = 0; i < size; i += SF_PAGE_SIZE) { for (i = 0; i < size; i += SF_PAGE_SIZE) {
n = min_t(u32, size - i, SF_PAGE_SIZE); n = min_t(u32, size - i, SF_PAGE_SIZE);
ret = t4_write_flash(adap, addr, n, cfg_data); ret = t4_write_flash(adap, addr, n, cfg_data, false);
if (ret) if (ret)
goto out; goto out;
@@ -10777,7 +10786,8 @@ int t4_load_bootcfg(struct adapter *adap, const u8 *cfg_data, unsigned int size)
for (i = 0; i < npad; i++) { for (i = 0; i < npad; i++) {
u8 data = 0; u8 data = 0;
ret = t4_write_flash(adap, cfg_addr + size + i, 1, &data); ret = t4_write_flash(adap, cfg_addr + size + i, 1, &data,
false);
if (ret) if (ret)
goto out; goto out;
} }