Commit d5002c9a authored by Vishal Kulkarni's avatar Vishal Kulkarni Committed by David S. Miller

cxgb4: add support to flash boot cfg image

Update set_flash to flash boot cfg image to flash region
Signed-off-by: default avatarVishal Kulkarni <vishal@chelsio.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 55088355
...@@ -143,6 +143,12 @@ enum { ...@@ -143,6 +143,12 @@ enum {
CXGB4_ETHTOOL_FLASH_FW = 1, CXGB4_ETHTOOL_FLASH_FW = 1,
CXGB4_ETHTOOL_FLASH_PHY = 2, CXGB4_ETHTOOL_FLASH_PHY = 2,
CXGB4_ETHTOOL_FLASH_BOOT = 3, CXGB4_ETHTOOL_FLASH_BOOT = 3,
CXGB4_ETHTOOL_FLASH_BOOTCFG = 4
};
struct cxgb4_bootcfg_data {
__le16 signature;
__u8 reserved[2];
}; };
struct cxgb4_pcir_data { struct cxgb4_pcir_data {
...@@ -183,6 +189,7 @@ struct legacy_pci_rom_hdr { ...@@ -183,6 +189,7 @@ struct legacy_pci_rom_hdr {
/* BOOT constants */ /* BOOT constants */
enum { enum {
BOOT_CFG_SIG = 0x4243,
BOOT_SIZE_INC = 512, BOOT_SIZE_INC = 512,
BOOT_SIGNATURE = 0xaa55, BOOT_SIGNATURE = 0xaa55,
BOOT_MIN_SIZE = sizeof(struct cxgb4_pci_exp_rom_header), BOOT_MIN_SIZE = sizeof(struct cxgb4_pci_exp_rom_header),
...@@ -2046,6 +2053,8 @@ int t4_i2c_rd(struct adapter *adap, unsigned int mbox, int port, ...@@ -2046,6 +2053,8 @@ int t4_i2c_rd(struct adapter *adap, unsigned int mbox, int port,
unsigned int len, u8 *buf); unsigned int len, u8 *buf);
int t4_load_boot(struct adapter *adap, u8 *boot_data, int t4_load_boot(struct adapter *adap, u8 *boot_data,
unsigned int boot_addr, unsigned int size); unsigned int boot_addr, unsigned int size);
int t4_load_bootcfg(struct adapter *adap,
const u8 *cfg_data, unsigned int size);
void free_rspq_fl(struct adapter *adap, struct sge_rspq *rq, struct sge_fl *fl); void free_rspq_fl(struct adapter *adap, struct sge_rspq *rq, struct sge_fl *fl);
void free_tx_desc(struct adapter *adap, struct sge_txq *q, void free_tx_desc(struct adapter *adap, struct sge_txq *q,
unsigned int n, bool unmap); unsigned int n, bool unmap);
......
...@@ -28,6 +28,7 @@ static const char * const flash_region_strings[] = { ...@@ -28,6 +28,7 @@ static const char * const flash_region_strings[] = {
"Firmware", "Firmware",
"PHY Firmware", "PHY Firmware",
"Boot", "Boot",
"Boot CFG",
}; };
static const char stats_strings[][ETH_GSTRING_LEN] = { static const char stats_strings[][ETH_GSTRING_LEN] = {
...@@ -1242,6 +1243,19 @@ static int set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, ...@@ -1242,6 +1243,19 @@ static int set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
return err; return err;
} }
static int cxgb4_ethtool_flash_bootcfg(struct net_device *netdev,
const u8 *data, u32 size)
{
struct adapter *adap = netdev2adap(netdev);
int ret;
ret = t4_load_bootcfg(adap, data, size);
if (ret)
dev_err(adap->pdev_dev, "Failed to load boot cfg image\n");
return ret;
}
static int cxgb4_ethtool_flash_boot(struct net_device *netdev, static int cxgb4_ethtool_flash_boot(struct net_device *netdev,
const u8 *bdata, u32 size) const u8 *bdata, u32 size)
{ {
...@@ -1336,6 +1350,9 @@ static int cxgb4_ethtool_flash_region(struct net_device *netdev, ...@@ -1336,6 +1350,9 @@ static int cxgb4_ethtool_flash_region(struct net_device *netdev,
case CXGB4_ETHTOOL_FLASH_BOOT: case CXGB4_ETHTOOL_FLASH_BOOT:
ret = cxgb4_ethtool_flash_boot(netdev, data, size); ret = cxgb4_ethtool_flash_boot(netdev, data, size);
break; break;
case CXGB4_ETHTOOL_FLASH_BOOTCFG:
ret = cxgb4_ethtool_flash_bootcfg(netdev, data, size);
break;
default: default:
ret = -EOPNOTSUPP; ret = -EOPNOTSUPP;
break; break;
...@@ -1365,6 +1382,17 @@ static int cxgb4_validate_fw_image(const u8 *data, u32 *size) ...@@ -1365,6 +1382,17 @@ static int cxgb4_validate_fw_image(const u8 *data, u32 *size)
return 0; return 0;
} }
static int cxgb4_validate_bootcfg_image(const u8 *data, u32 *size)
{
struct cxgb4_bootcfg_data *header;
header = (struct cxgb4_bootcfg_data *)data;
if (le16_to_cpu(header->signature) != BOOT_CFG_SIG)
return -EINVAL;
return 0;
}
static int cxgb4_validate_boot_image(const u8 *data, u32 *size) static int cxgb4_validate_boot_image(const u8 *data, u32 *size)
{ {
struct cxgb4_pci_exp_rom_header *exp_header; struct cxgb4_pci_exp_rom_header *exp_header;
...@@ -1401,6 +1429,8 @@ static int cxgb4_ethtool_get_flash_region(const u8 *data, u32 *size) ...@@ -1401,6 +1429,8 @@ static int cxgb4_ethtool_get_flash_region(const u8 *data, u32 *size)
return CXGB4_ETHTOOL_FLASH_BOOT; return CXGB4_ETHTOOL_FLASH_BOOT;
if (!cxgb4_validate_phy_image(data, size)) if (!cxgb4_validate_phy_image(data, size))
return CXGB4_ETHTOOL_FLASH_PHY; return CXGB4_ETHTOOL_FLASH_PHY;
if (!cxgb4_validate_bootcfg_image(data, size))
return CXGB4_ETHTOOL_FLASH_BOOTCFG;
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
......
...@@ -10668,3 +10668,93 @@ int t4_load_boot(struct adapter *adap, u8 *boot_data, ...@@ -10668,3 +10668,93 @@ int t4_load_boot(struct adapter *adap, u8 *boot_data,
ret); ret);
return ret; return ret;
} }
/**
* t4_flash_bootcfg_addr - return the address of the flash
* optionrom configuration
* @adapter: the adapter
*
* Return the address within the flash where the OptionROM Configuration
* is stored, or an error if the device FLASH is too small to contain
* a OptionROM Configuration.
*/
static int t4_flash_bootcfg_addr(struct adapter *adapter)
{
/**
* If the device FLASH isn't large enough to hold a Firmware
* Configuration File, return an error.
*/
if (adapter->params.sf_size <
FLASH_BOOTCFG_START + FLASH_BOOTCFG_MAX_SIZE)
return -ENOSPC;
return FLASH_BOOTCFG_START;
}
int t4_load_bootcfg(struct adapter *adap, const u8 *cfg_data, unsigned int size)
{
unsigned int sf_sec_size = adap->params.sf_size / adap->params.sf_nsec;
struct cxgb4_bootcfg_data *header;
unsigned int flash_cfg_start_sec;
unsigned int addr, npad;
int ret, i, n, cfg_addr;
cfg_addr = t4_flash_bootcfg_addr(adap);
if (cfg_addr < 0)
return cfg_addr;
addr = cfg_addr;
flash_cfg_start_sec = addr / SF_SEC_SIZE;
if (size > FLASH_BOOTCFG_MAX_SIZE) {
dev_err(adap->pdev_dev, "bootcfg file too large, max is %u bytes\n",
FLASH_BOOTCFG_MAX_SIZE);
return -EFBIG;
}
header = (struct cxgb4_bootcfg_data *)cfg_data;
if (le16_to_cpu(header->signature) != BOOT_CFG_SIG) {
dev_err(adap->pdev_dev, "Wrong bootcfg signature\n");
ret = -EINVAL;
goto out;
}
i = DIV_ROUND_UP(FLASH_BOOTCFG_MAX_SIZE,
sf_sec_size);
ret = t4_flash_erase_sectors(adap, flash_cfg_start_sec,
flash_cfg_start_sec + i - 1);
/**
* If size == 0 then we're simply erasing the FLASH sectors associated
* with the on-adapter OptionROM Configuration File.
*/
if (ret || size == 0)
goto out;
/* this will write to the flash up to SF_PAGE_SIZE at a time */
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);
if (ret)
goto out;
addr += SF_PAGE_SIZE;
cfg_data += SF_PAGE_SIZE;
}
npad = ((size + 4 - 1) & ~3) - size;
for (i = 0; i < npad; i++) {
u8 data = 0;
ret = t4_write_flash(adap, cfg_addr + size + i, 1, &data);
if (ret)
goto out;
}
out:
if (ret)
dev_err(adap->pdev_dev, "boot config data %s failed %d\n",
(size == 0 ? "clear" : "download"), ret);
return ret;
}
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