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

cxgb4: update set_flash to flash different images

Chelsio adapter contains different flash regions and each
region is used by different binary files. This patch adds
support to flash images like PHY firmware, boot and boot config
using ethtool -f N.

The N value mapping is as follows.
N = 0 : Parse image and decide which region to flash
N = 1 : Firmware
N = 2 : PHY firmware
N = 3 : boot image
N = 4 : boot cfg

Signed-off-by: Vishal Kulkarni <vishal@chelsio.com>"
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 0fb9fbab
......@@ -139,6 +139,10 @@ enum cc_fec {
FEC_BASER_RS = 1 << 2 /* BaseR/Reed-Solomon */
};
enum {
CXGB4_ETHTOOL_FLASH_FW = 1,
};
struct port_stats {
u64 tx_octets; /* total # of octets in good frames */
u64 tx_frames; /* all good frames */
......@@ -492,6 +496,11 @@ struct trace_params {
unsigned char port;
};
struct cxgb4_fw_data {
__be32 signature;
__u8 reserved[4];
};
/* Firmware Port Capabilities types. */
typedef u16 fw_port_cap16_t; /* 16-bit Port Capabilities integral value */
......
......@@ -23,6 +23,11 @@ static void set_msglevel(struct net_device *dev, u32 val)
netdev2adap(dev)->msg_enable = val;
}
static const char * const flash_region_strings[] = {
"All",
"Firmware",
};
static const char stats_strings[][ETH_GSTRING_LEN] = {
"tx_octets_ok ",
"tx_frames_ok ",
......@@ -1235,15 +1240,88 @@ static int set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
return err;
}
static int set_flash(struct net_device *netdev, struct ethtool_flash *ef)
static int cxgb4_ethtool_flash_fw(struct net_device *netdev,
const u8 *data, u32 size)
{
int ret;
const struct firmware *fw;
struct adapter *adap = netdev2adap(netdev);
unsigned int mbox = PCIE_FW_MASTER_M + 1;
u32 pcie_fw;
int ret;
/* If the adapter has been fully initialized then we'll go ahead and
* try to get the firmware's cooperation in upgrading to the new
* firmware image otherwise we'll try to do the entire job from the
* host ... and we always "force" the operation in this path.
*/
if (adap->flags & CXGB4_FULL_INIT_DONE)
mbox = adap->mbox;
ret = t4_fw_upgrade(adap, mbox, data, size, 1);
if (ret)
dev_err(adap->pdev_dev,
"Failed to flash firmware\n");
return ret;
}
static int cxgb4_ethtool_flash_region(struct net_device *netdev,
const u8 *data, u32 size, u32 region)
{
struct adapter *adap = netdev2adap(netdev);
int ret;
switch (region) {
case CXGB4_ETHTOOL_FLASH_FW:
ret = cxgb4_ethtool_flash_fw(netdev, data, size);
break;
default:
ret = -EOPNOTSUPP;
break;
}
if (!ret)
dev_info(adap->pdev_dev,
"loading %s successful, reload cxgb4 driver\n",
flash_region_strings[region]);
return ret;
}
#define CXGB4_FW_SIG 0x4368656c
#define CXGB4_FW_SIG_OFFSET 0x160
static int cxgb4_validate_fw_image(const u8 *data, u32 *size)
{
struct cxgb4_fw_data *header;
header = (struct cxgb4_fw_data *)&data[CXGB4_FW_SIG_OFFSET];
if (be32_to_cpu(header->signature) != CXGB4_FW_SIG)
return -EINVAL;
if (size)
*size = be16_to_cpu(((struct fw_hdr *)data)->len512) * 512;
return 0;
}
static int cxgb4_ethtool_get_flash_region(const u8 *data, u32 *size)
{
if (!cxgb4_validate_fw_image(data, size))
return CXGB4_ETHTOOL_FLASH_FW;
return -EOPNOTSUPP;
}
static int set_flash(struct net_device *netdev, struct ethtool_flash *ef)
{
struct adapter *adap = netdev2adap(netdev);
const struct firmware *fw;
unsigned int master;
u8 master_vld = 0;
const u8 *fw_data;
size_t fw_size;
u32 size = 0;
u32 pcie_fw;
int region;
int ret;
pcie_fw = t4_read_reg(adap, PCIE_FW_A);
master = PCIE_FW_MASTER_G(pcie_fw);
......@@ -1261,19 +1339,32 @@ static int set_flash(struct net_device *netdev, struct ethtool_flash *ef)
if (ret < 0)
return ret;
/* If the adapter has been fully initialized then we'll go ahead and
* try to get the firmware's cooperation in upgrading to the new
* firmware image otherwise we'll try to do the entire job from the
* host ... and we always "force" the operation in this path.
*/
if (adap->flags & CXGB4_FULL_INIT_DONE)
mbox = adap->mbox;
fw_data = fw->data;
fw_size = fw->size;
if (ef->region == ETHTOOL_FLASH_ALL_REGIONS) {
while (fw_size > 0) {
size = 0;
region = cxgb4_ethtool_get_flash_region(fw_data, &size);
if (region < 0 || !size) {
ret = region;
goto out_free_fw;
}
ret = cxgb4_ethtool_flash_region(netdev, fw_data, size,
region);
if (ret)
goto out_free_fw;
fw_data += size;
fw_size -= size;
}
} else {
ret = cxgb4_ethtool_flash_region(netdev, fw_data, fw_size,
ef->region);
}
ret = t4_fw_upgrade(adap, mbox, fw->data, fw->size, 1);
out_free_fw:
release_firmware(fw);
if (!ret)
dev_info(adap->pdev_dev,
"loaded firmware %s, reload cxgb4 driver\n", ef->data);
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