Commit f4cdcae0 authored by David S. Miller's avatar David S. Miller

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: default avatarDavid S. Miller <davem@davemloft.net>
parents 33e38144 6d297540
...@@ -1337,13 +1337,27 @@ static int cxgb4_ethtool_flash_phy(struct net_device *netdev, ...@@ -1337,13 +1337,27 @@ static int cxgb4_ethtool_flash_phy(struct net_device *netdev,
return ret; return ret;
} }
spin_lock_bh(&adap->win0_lock); /* We have to RESET the chip/firmware because we need the
ret = t4_load_phy_fw(adap, MEMWIN_NIC, NULL, data, size); * chip in uninitialized state for loading new PHY image.
spin_unlock_bh(&adap->win0_lock); * Otherwise, the running firmware will only store the PHY
if (ret) * image in local RAM which will be lost after next reset.
dev_err(adap->pdev_dev, "Failed to load PHY FW\n"); */
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;
}
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 ret;
}
return 0;
} }
static int cxgb4_ethtool_flash_fw(struct net_device *netdev, static int cxgb4_ethtool_flash_fw(struct net_device *netdev,
......
...@@ -4424,10 +4424,8 @@ static int adap_init0_phy(struct adapter *adap) ...@@ -4424,10 +4424,8 @@ static int adap_init0_phy(struct adapter *adap)
/* Load PHY Firmware onto adapter. /* Load PHY Firmware onto adapter.
*/ */
spin_lock_bh(&adap->win0_lock);
ret = t4_load_phy_fw(adap, MEMWIN_NIC, phy_info->phy_fw_version, ret = t4_load_phy_fw(adap, MEMWIN_NIC, phy_info->phy_fw_version,
(u8 *)phyf->data, phyf->size); (u8 *)phyf->data, phyf->size);
spin_unlock_bh(&adap->win0_lock);
if (ret < 0) if (ret < 0)
dev_err(adap->pdev_dev, "PHY Firmware transfer error %d\n", dev_err(adap->pdev_dev, "PHY Firmware transfer error %d\n",
-ret); -ret);
......
...@@ -3060,16 +3060,19 @@ int t4_read_flash(struct adapter *adapter, unsigned int addr, ...@@ -3060,16 +3060,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;
...@@ -3080,10 +3083,14 @@ static int t4_write_flash(struct adapter *adapter, unsigned int addr, ...@@ -3080,10 +3083,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)
...@@ -3096,7 +3103,8 @@ static int t4_write_flash(struct adapter *adapter, unsigned int addr, ...@@ -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 */ 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;
...@@ -3692,7 +3700,7 @@ int t4_load_fw(struct adapter *adap, const u8 *fw_data, unsigned int size) ...@@ -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); 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;
...@@ -3700,14 +3708,14 @@ int t4_load_fw(struct adapter *adap, const u8 *fw_data, unsigned int size) ...@@ -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) { 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",
...@@ -3812,9 +3820,11 @@ int t4_load_phy_fw(struct adapter *adap, int win, ...@@ -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 /* Copy the supplied PHY Firmware image to the adapter memory location
* allocated by the adapter firmware. * allocated by the adapter firmware.
*/ */
spin_lock_bh(&adap->win0_lock);
ret = t4_memory_rw(adap, win, mtype, maddr, ret = t4_memory_rw(adap, win, mtype, maddr,
phy_fw_size, (__be32 *)phy_fw_data, phy_fw_size, (__be32 *)phy_fw_data,
T4_MEMORY_WRITE); T4_MEMORY_WRITE);
spin_unlock_bh(&adap->win0_lock);
if (ret) if (ret)
return ret; return ret;
...@@ -10208,7 +10218,7 @@ int t4_load_cfg(struct adapter *adap, const u8 *cfg_data, unsigned int size) ...@@ -10208,7 +10218,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;
...@@ -10677,13 +10687,14 @@ int t4_load_boot(struct adapter *adap, u8 *boot_data, ...@@ -10677,13 +10687,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)
...@@ -10758,7 +10769,7 @@ int t4_load_bootcfg(struct adapter *adap, const u8 *cfg_data, unsigned int size) ...@@ -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) { 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;
...@@ -10770,7 +10781,8 @@ int t4_load_bootcfg(struct adapter *adap, const u8 *cfg_data, unsigned int size) ...@@ -10770,7 +10781,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;
} }
......
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