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

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
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -143,6 +143,12 @@ enum {
	CXGB4_ETHTOOL_FLASH_FW = 1,
	CXGB4_ETHTOOL_FLASH_PHY = 2,
	CXGB4_ETHTOOL_FLASH_BOOT = 3,
	CXGB4_ETHTOOL_FLASH_BOOTCFG = 4
};

struct cxgb4_bootcfg_data {
	__le16 signature;
	__u8 reserved[2];
};

struct cxgb4_pcir_data {
@@ -183,6 +189,7 @@ struct legacy_pci_rom_hdr {

/* BOOT constants */
enum {
	BOOT_CFG_SIG = 0x4243,
	BOOT_SIZE_INC = 512,
	BOOT_SIGNATURE = 0xaa55,
	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,
	      unsigned int len, u8 *buf);
int t4_load_boot(struct adapter *adap, u8 *boot_data,
		 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_tx_desc(struct adapter *adap, struct sge_txq *q,
		  unsigned int n, bool unmap);
+30 −0
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ static const char * const flash_region_strings[] = {
	"Firmware",
	"PHY Firmware",
	"Boot",
	"Boot CFG",
};

static const char stats_strings[][ETH_GSTRING_LEN] = {
@@ -1242,6 +1243,19 @@ out:
	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,
				    const u8 *bdata, u32 size)
{
@@ -1336,6 +1350,9 @@ static int cxgb4_ethtool_flash_region(struct net_device *netdev,
	case CXGB4_ETHTOOL_FLASH_BOOT:
		ret = cxgb4_ethtool_flash_boot(netdev, data, size);
		break;
	case CXGB4_ETHTOOL_FLASH_BOOTCFG:
		ret = cxgb4_ethtool_flash_bootcfg(netdev, data, size);
		break;
	default:
		ret = -EOPNOTSUPP;
		break;
@@ -1365,6 +1382,17 @@ static int cxgb4_validate_fw_image(const u8 *data, u32 *size)
	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)
{
	struct cxgb4_pci_exp_rom_header *exp_header;
@@ -1401,6 +1429,8 @@ static int cxgb4_ethtool_get_flash_region(const u8 *data, u32 *size)
		return CXGB4_ETHTOOL_FLASH_BOOT;
	if (!cxgb4_validate_phy_image(data, size))
		return CXGB4_ETHTOOL_FLASH_PHY;
	if (!cxgb4_validate_bootcfg_image(data, size))
		return CXGB4_ETHTOOL_FLASH_BOOTCFG;

	return -EOPNOTSUPP;
}
+90 −0
Original line number Diff line number Diff line
@@ -10668,3 +10668,93 @@ out:
			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;
}