Skip to content

Commit

Permalink
vxge: add support for ethtool firmware flashing
Browse files Browse the repository at this point in the history
Add the ability in the vxge driver to flash firmware via ethtool.

Updated to include comments from Ben Hutchings.

Signed-off-by: Jon Mason <jon.mason@exar.com>
Signed-off-by: Ram Vepa <ram.vepa@exar.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Jon Mason authored and David S. Miller committed Nov 11, 2010
1 parent 8424e00 commit e8ac175
Show file tree
Hide file tree
Showing 7 changed files with 500 additions and 22 deletions.
183 changes: 182 additions & 1 deletion drivers/net/vxge/vxge-config.c
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,6 @@ __vxge_hw_vpath_reset_check(struct __vxge_hw_virtualpath *vpath);
static enum vxge_hw_status
__vxge_hw_vpath_sw_reset(struct __vxge_hw_device *devh, u32 vp_id);


static enum vxge_hw_status
__vxge_hw_vpath_mac_configure(struct __vxge_hw_device *devh, u32 vp_id);

Expand Down Expand Up @@ -322,6 +321,188 @@ vxge_hw_vpath_fw_api(struct __vxge_hw_virtualpath *vpath, u32 action,
return status;
}

enum vxge_hw_status
vxge_hw_upgrade_read_version(struct __vxge_hw_device *hldev, u32 *major,
u32 *minor, u32 *build)
{
u64 data0 = 0, data1 = 0, steer_ctrl = 0;
struct __vxge_hw_virtualpath *vpath;
enum vxge_hw_status status;

vpath = &hldev->virtual_paths[hldev->first_vp_id];

status = vxge_hw_vpath_fw_api(vpath,
VXGE_HW_FW_UPGRADE_ACTION,
VXGE_HW_FW_UPGRADE_MEMO,
VXGE_HW_FW_UPGRADE_OFFSET_READ,
&data0, &data1, &steer_ctrl);
if (status != VXGE_HW_OK)
return status;

*major = VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_MAJOR(data0);
*minor = VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_MINOR(data0);
*build = VXGE_HW_RTS_ACCESS_STEER_DATA0_GET_FW_VER_BUILD(data0);

return status;
}

enum vxge_hw_status vxge_hw_flash_fw(struct __vxge_hw_device *hldev)
{
u64 data0 = 0, data1 = 0, steer_ctrl = 0;
struct __vxge_hw_virtualpath *vpath;
enum vxge_hw_status status;
u32 ret;

vpath = &hldev->virtual_paths[hldev->first_vp_id];

status = vxge_hw_vpath_fw_api(vpath,
VXGE_HW_FW_UPGRADE_ACTION,
VXGE_HW_FW_UPGRADE_MEMO,
VXGE_HW_FW_UPGRADE_OFFSET_COMMIT,
&data0, &data1, &steer_ctrl);
if (status != VXGE_HW_OK) {
vxge_debug_init(VXGE_ERR, "%s: FW upgrade failed", __func__);
goto exit;
}

ret = VXGE_HW_RTS_ACCESS_STEER_CTRL_GET_ACTION(steer_ctrl) & 0x7F;
if (ret != 1) {
vxge_debug_init(VXGE_ERR, "%s: FW commit failed with error %d",
__func__, ret);
status = VXGE_HW_FAIL;
}

exit:
return status;
}

enum vxge_hw_status
vxge_update_fw_image(struct __vxge_hw_device *hldev, const u8 *fwdata, int size)
{
u64 data0 = 0, data1 = 0, steer_ctrl = 0;
struct __vxge_hw_virtualpath *vpath;
enum vxge_hw_status status;
int ret_code, sec_code;

vpath = &hldev->virtual_paths[hldev->first_vp_id];

/* send upgrade start command */
status = vxge_hw_vpath_fw_api(vpath,
VXGE_HW_FW_UPGRADE_ACTION,
VXGE_HW_FW_UPGRADE_MEMO,
VXGE_HW_FW_UPGRADE_OFFSET_START,
&data0, &data1, &steer_ctrl);
if (status != VXGE_HW_OK) {
vxge_debug_init(VXGE_ERR, " %s: Upgrade start cmd failed",
__func__);
return status;
}

/* Transfer fw image to adapter 16 bytes at a time */
for (; size > 0; size -= VXGE_HW_FW_UPGRADE_BLK_SIZE) {
steer_ctrl = 0;

/* The next 128bits of fwdata to be loaded onto the adapter */
data0 = *((u64 *)fwdata);
data1 = *((u64 *)fwdata + 1);

status = vxge_hw_vpath_fw_api(vpath,
VXGE_HW_FW_UPGRADE_ACTION,
VXGE_HW_FW_UPGRADE_MEMO,
VXGE_HW_FW_UPGRADE_OFFSET_SEND,
&data0, &data1, &steer_ctrl);
if (status != VXGE_HW_OK) {
vxge_debug_init(VXGE_ERR, "%s: Upgrade send failed",
__func__);
goto out;
}

ret_code = VXGE_HW_UPGRADE_GET_RET_ERR_CODE(data0);
switch (ret_code) {
case VXGE_HW_FW_UPGRADE_OK:
/* All OK, send next 16 bytes. */
break;
case VXGE_FW_UPGRADE_BYTES2SKIP:
/* skip bytes in the stream */
fwdata += (data0 >> 8) & 0xFFFFFFFF;
break;
case VXGE_HW_FW_UPGRADE_DONE:
goto out;
case VXGE_HW_FW_UPGRADE_ERR:
sec_code = VXGE_HW_UPGRADE_GET_SEC_ERR_CODE(data0);
switch (sec_code) {
case VXGE_HW_FW_UPGRADE_ERR_CORRUPT_DATA_1:
case VXGE_HW_FW_UPGRADE_ERR_CORRUPT_DATA_7:
printk(KERN_ERR
"corrupted data from .ncf file\n");
break;
case VXGE_HW_FW_UPGRADE_ERR_INV_NCF_FILE_3:
case VXGE_HW_FW_UPGRADE_ERR_INV_NCF_FILE_4:
case VXGE_HW_FW_UPGRADE_ERR_INV_NCF_FILE_5:
case VXGE_HW_FW_UPGRADE_ERR_INV_NCF_FILE_6:
case VXGE_HW_FW_UPGRADE_ERR_INV_NCF_FILE_8:
printk(KERN_ERR "invalid .ncf file\n");
break;
case VXGE_HW_FW_UPGRADE_ERR_BUFFER_OVERFLOW:
printk(KERN_ERR "buffer overflow\n");
break;
case VXGE_HW_FW_UPGRADE_ERR_FAILED_TO_FLASH:
printk(KERN_ERR "failed to flash the image\n");
break;
case VXGE_HW_FW_UPGRADE_ERR_GENERIC_ERROR_UNKNOWN:
printk(KERN_ERR
"generic error. Unknown error type\n");
break;
default:
printk(KERN_ERR "Unknown error of type %d\n",
sec_code);
break;
}
status = VXGE_HW_FAIL;
goto out;
default:
printk(KERN_ERR "Unknown FW error: %d\n", ret_code);
status = VXGE_HW_FAIL;
goto out;
}
/* point to next 16 bytes */
fwdata += VXGE_HW_FW_UPGRADE_BLK_SIZE;
}
out:
return status;
}

enum vxge_hw_status
vxge_hw_vpath_eprom_img_ver_get(struct __vxge_hw_device *hldev,
struct eprom_image *img)
{
u64 data0 = 0, data1 = 0, steer_ctrl = 0;
struct __vxge_hw_virtualpath *vpath;
enum vxge_hw_status status;
int i;

vpath = &hldev->virtual_paths[hldev->first_vp_id];

for (i = 0; i < VXGE_HW_MAX_ROM_IMAGES; i++) {
data0 = VXGE_HW_RTS_ACCESS_STEER_ROM_IMAGE_INDEX(i);
data1 = steer_ctrl = 0;

status = vxge_hw_vpath_fw_api(vpath,
VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_FW_MEMO,
VXGE_HW_FW_API_GET_EPROM_REV,
0, &data0, &data1, &steer_ctrl);
if (status != VXGE_HW_OK)
break;

img[i].is_valid = VXGE_HW_GET_EPROM_IMAGE_VALID(data0);
img[i].index = VXGE_HW_GET_EPROM_IMAGE_INDEX(data0);
img[i].type = VXGE_HW_GET_EPROM_IMAGE_TYPE(data0);
img[i].version = VXGE_HW_GET_EPROM_IMAGE_REV(data0);
}

return status;
}

/*
* __vxge_hw_channel_allocate - Allocate memory for channel
* This function allocates required memory for the channel and various arrays
Expand Down
71 changes: 68 additions & 3 deletions drivers/net/vxge/vxge-config.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,15 @@
#define VXGE_HW_MAX_MTU 9600
#define VXGE_HW_DEFAULT_MTU 1500

#define VXGE_HW_MAX_ROM_IMAGES 8

struct eprom_image {
u8 is_valid:1;
u8 index;
u8 type;
u16 version;
};

#ifdef VXGE_DEBUG_ASSERT
/**
* vxge_assert
Expand Down Expand Up @@ -147,6 +156,47 @@ enum vxge_hw_device_link_state {
VXGE_HW_LINK_UP
};

/**
* enum enum vxge_hw_fw_upgrade_code - FW upgrade return codes.
* @VXGE_HW_FW_UPGRADE_OK: All OK send next 16 bytes
* @VXGE_HW_FW_UPGRADE_DONE: upload completed
* @VXGE_HW_FW_UPGRADE_ERR: upload error
* @VXGE_FW_UPGRADE_BYTES2SKIP: skip bytes in the stream
*
*/
enum vxge_hw_fw_upgrade_code {
VXGE_HW_FW_UPGRADE_OK = 0,
VXGE_HW_FW_UPGRADE_DONE = 1,
VXGE_HW_FW_UPGRADE_ERR = 2,
VXGE_FW_UPGRADE_BYTES2SKIP = 3
};

/**
* enum enum vxge_hw_fw_upgrade_err_code - FW upgrade error codes.
* @VXGE_HW_FW_UPGRADE_ERR_CORRUPT_DATA_1: corrupt data
* @VXGE_HW_FW_UPGRADE_ERR_BUFFER_OVERFLOW: buffer overflow
* @VXGE_HW_FW_UPGRADE_ERR_INV_NCF_FILE_3: invalid .ncf file
* @VXGE_HW_FW_UPGRADE_ERR_INV_NCF_FILE_4: invalid .ncf file
* @VXGE_HW_FW_UPGRADE_ERR_INV_NCF_FILE_5: invalid .ncf file
* @VXGE_HW_FW_UPGRADE_ERR_INV_NCF_FILE_6: invalid .ncf file
* @VXGE_HW_FW_UPGRADE_ERR_CORRUPT_DATA_7: corrupt data
* @VXGE_HW_FW_UPGRADE_ERR_INV_NCF_FILE_8: invalid .ncf file
* @VXGE_HW_FW_UPGRADE_ERR_GENERIC_ERROR_UNKNOWN: generic error unknown type
* @VXGE_HW_FW_UPGRADE_ERR_FAILED_TO_FLASH: failed to flash image check failed
*/
enum vxge_hw_fw_upgrade_err_code {
VXGE_HW_FW_UPGRADE_ERR_CORRUPT_DATA_1 = 1,
VXGE_HW_FW_UPGRADE_ERR_BUFFER_OVERFLOW = 2,
VXGE_HW_FW_UPGRADE_ERR_INV_NCF_FILE_3 = 3,
VXGE_HW_FW_UPGRADE_ERR_INV_NCF_FILE_4 = 4,
VXGE_HW_FW_UPGRADE_ERR_INV_NCF_FILE_5 = 5,
VXGE_HW_FW_UPGRADE_ERR_INV_NCF_FILE_6 = 6,
VXGE_HW_FW_UPGRADE_ERR_CORRUPT_DATA_7 = 7,
VXGE_HW_FW_UPGRADE_ERR_INV_NCF_FILE_8 = 8,
VXGE_HW_FW_UPGRADE_ERR_GENERIC_ERROR_UNKNOWN = 9,
VXGE_HW_FW_UPGRADE_ERR_FAILED_TO_FLASH = 10
};

/**
* struct vxge_hw_device_date - Date Format
* @day: Day
Expand Down Expand Up @@ -454,7 +504,6 @@ struct vxge_hw_device_config {
* See also: vxge_hw_driver_initialize().
*/
struct vxge_hw_uld_cbs {

void (*link_up)(struct __vxge_hw_device *devh);
void (*link_down)(struct __vxge_hw_device *devh);
void (*crit_err)(struct __vxge_hw_device *devh,
Expand Down Expand Up @@ -721,6 +770,7 @@ struct __vxge_hw_device {
u32 debug_level;
u32 level_err;
u32 level_trace;
u16 eprom_versions[VXGE_HW_MAX_ROM_IMAGES];
};

#define VXGE_HW_INFO_LEN 64
Expand Down Expand Up @@ -2032,7 +2082,22 @@ __vxge_hw_device_is_privilaged(u32 host_type, u32 func_id);
#define VXGE_HW_MIN_SUCCESSIVE_IDLE_COUNT 5
#define VXGE_HW_MAX_POLLING_COUNT 100

int vxge_hw_vpath_wait_receive_idle(struct __vxge_hw_device *hldev, u32 vp_id);
void
vxge_hw_device_wait_receive_idle(struct __vxge_hw_device *hldev);

enum vxge_hw_status
vxge_hw_upgrade_read_version(struct __vxge_hw_device *hldev, u32 *major,
u32 *minor, u32 *build);

enum vxge_hw_status vxge_hw_flash_fw(struct __vxge_hw_device *hldev);

void vxge_hw_device_wait_receive_idle(struct __vxge_hw_device *hldev);
enum vxge_hw_status
vxge_update_fw_image(struct __vxge_hw_device *hldev, const u8 *filebuf,
int size);

enum vxge_hw_status
vxge_hw_vpath_eprom_img_ver_get(struct __vxge_hw_device *hldev,
struct eprom_image *eprom_image_data);

int vxge_hw_vpath_wait_receive_idle(struct __vxge_hw_device *hldev, u32 vp_id);
#endif
20 changes: 20 additions & 0 deletions drivers/net/vxge/vxge-ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -1153,6 +1153,25 @@ static int vxge_set_flags(struct net_device *dev, u32 data)
return 0;
}

static int vxge_fw_flash(struct net_device *dev, struct ethtool_flash *parms)
{
struct vxgedev *vdev = (struct vxgedev *)netdev_priv(dev);

if (vdev->max_vpath_supported != VXGE_HW_MAX_VIRTUAL_PATHS) {
printk(KERN_INFO "Single Function Mode is required to flash the"
" firmware\n");
return -EINVAL;
}

if (netif_running(dev)) {
printk(KERN_INFO "Interface %s must be down to flash the "
"firmware\n", dev->name);
return -EBUSY;
}

return vxge_fw_upgrade(vdev, parms->data, 1);
}

static const struct ethtool_ops vxge_ethtool_ops = {
.get_settings = vxge_ethtool_gset,
.set_settings = vxge_ethtool_sset,
Expand All @@ -1175,6 +1194,7 @@ static const struct ethtool_ops vxge_ethtool_ops = {
.get_sset_count = vxge_ethtool_get_sset_count,
.get_ethtool_stats = vxge_get_ethtool_stats,
.set_flags = vxge_set_flags,
.flash_device = vxge_fw_flash,
};

void vxge_initialize_ethtool_ops(struct net_device *ndev)
Expand Down
Loading

0 comments on commit e8ac175

Please sign in to comment.