Merge branch 'cxgb4-fixes'

Rahul Lakkireddy says:

====================
cxgb4: bug fixes for ethtool flash ops

This series of patches add bug fixes in ethtool flash operations.

Patch 1 fixes an endianness issue when writing boot image to flash
after the device ID has been updated.

Patch 2 fixes sleep in atomic when writing PHY firmware to flash.

Patch 3 fixes issue with PHY firmware image not getting written to
flash when chip is still running.
-====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2021-06-11 11:15:01 -07:00
commit f4cdcae03f
3 changed files with 49 additions and 25 deletions

View file

@ -1337,13 +1337,27 @@ static int cxgb4_ethtool_flash_phy(struct net_device *netdev,
return ret;
}
spin_lock_bh(&adap->win0_lock);
ret = t4_load_phy_fw(adap, MEMWIN_NIC, NULL, data, size);
spin_unlock_bh(&adap->win0_lock);
if (ret)
dev_err(adap->pdev_dev, "Failed to load PHY FW\n");
/* We have to RESET the chip/firmware because we need the
* chip in uninitialized state for loading new PHY image.
* Otherwise, the running firmware will only store the PHY
* image in local RAM which will be lost after next reset.
*/
ret = t4_fw_reset(adap, adap->mbox, PIORSTMODE_F | PIORST_F);
if (ret < 0) {
dev_err(adap->pdev_dev,
"Set FW to RESET for flashing PHY FW failed. ret: %d\n",
ret);
return ret;
}
return ret;
ret = t4_load_phy_fw(adap, MEMWIN_NIC, NULL, data, size);
if (ret < 0) {
dev_err(adap->pdev_dev, "Failed to load PHY FW. ret: %d\n",
ret);
return ret;
}
return 0;
}
static int cxgb4_ethtool_flash_fw(struct net_device *netdev,

View file

@ -4424,10 +4424,8 @@ static int adap_init0_phy(struct adapter *adap)
/* Load PHY Firmware onto adapter.
*/
spin_lock_bh(&adap->win0_lock);
ret = t4_load_phy_fw(adap, MEMWIN_NIC, phy_info->phy_fw_version,
(u8 *)phyf->data, phyf->size);
spin_unlock_bh(&adap->win0_lock);
if (ret < 0)
dev_err(adap->pdev_dev, "PHY Firmware transfer error %d\n",
-ret);

View file

@ -3060,16 +3060,19 @@ int t4_read_flash(struct adapter *adapter, unsigned int addr,
* @addr: the start address to write
* @n: length of data to write in bytes
* @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
* 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,
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;
u32 buf[64];
int ret;
if (addr >= adapter->params.sf_size || offset + n > SF_PAGE_SIZE)
return -EINVAL;
@ -3080,10 +3083,14 @@ static int t4_write_flash(struct adapter *adapter, unsigned int addr,
(ret = sf1_write(adapter, 4, 1, 1, val)) != 0)
goto unlock;
for (left = n; left; left -= c) {
for (left = n; left; left -= c, data += c) {
c = min(left, 4U);
for (val = 0, i = 0; i < c; ++i)
val = (val << 8) + *data++;
for (val = 0, i = 0; i < c; ++i) {
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);
if (ret)
@ -3096,7 +3103,8 @@ static int t4_write_flash(struct adapter *adapter, unsigned int addr,
t4_write_reg(adapter, SF_OP_A, 0); /* unlock SF */
/* 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)
return ret;
@ -3692,7 +3700,7 @@ int t4_load_fw(struct adapter *adap, const u8 *fw_data, unsigned int size)
*/
memcpy(first_page, fw_data, SF_PAGE_SIZE);
((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)
goto out;
@ -3700,14 +3708,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) {
addr += 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)
goto out;
}
ret = t4_write_flash(adap,
fw_start + offsetof(struct fw_hdr, fw_ver),
sizeof(hdr->fw_ver), (const u8 *)&hdr->fw_ver);
ret = t4_write_flash(adap, fw_start + offsetof(struct fw_hdr, fw_ver),
sizeof(hdr->fw_ver), (const u8 *)&hdr->fw_ver,
true);
out:
if (ret)
dev_err(adap->pdev_dev, "firmware download failed, error %d\n",
@ -3812,9 +3820,11 @@ int t4_load_phy_fw(struct adapter *adap, int win,
/* Copy the supplied PHY Firmware image to the adapter memory location
* allocated by the adapter firmware.
*/
spin_lock_bh(&adap->win0_lock);
ret = t4_memory_rw(adap, win, mtype, maddr,
phy_fw_size, (__be32 *)phy_fw_data,
T4_MEMORY_WRITE);
spin_unlock_bh(&adap->win0_lock);
if (ret)
return ret;
@ -10208,7 +10218,7 @@ int t4_load_cfg(struct adapter *adap, const u8 *cfg_data, unsigned int size)
n = size - i;
else
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)
goto out;
@ -10677,13 +10687,14 @@ int t4_load_boot(struct adapter *adap, u8 *boot_data,
for (size -= SF_PAGE_SIZE; size; size -= SF_PAGE_SIZE) {
addr += 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)
goto out;
}
ret = t4_write_flash(adap, boot_sector, SF_PAGE_SIZE,
(const u8 *)header);
(const u8 *)header, false);
out:
if (ret)
@ -10758,7 +10769,7 @@ int t4_load_bootcfg(struct adapter *adap, const u8 *cfg_data, unsigned int size)
for (i = 0; i < 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)
goto out;
@ -10770,7 +10781,8 @@ int t4_load_bootcfg(struct adapter *adap, const u8 *cfg_data, unsigned int size)
for (i = 0; i < npad; i++) {
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)
goto out;
}