Commit 2e283962 authored by Divy Le Ray's avatar Divy Le Ray Committed by Jeff Garzik

cxgb3 - Auto-load FW if mismatch detected

The driver attempts to upgrade the FW if the card has the wrong version.
Signed-off-by: default avatarDivy Le Ray <divy@chelsio.com>
Signed-off-by: default avatarJeff Garzik <jeff@garzik.org>
parent 05b97b30
......@@ -2374,6 +2374,7 @@ config CHELSIO_T1_NAPI
config CHELSIO_T3
tristate "Chelsio Communications T3 10Gb Ethernet support"
depends on PCI
select FW_LOADER
help
This driver supports Chelsio T3-based gigabit and 10Gb Ethernet
adapters.
......
......@@ -42,6 +42,7 @@
#include <linux/workqueue.h>
#include <linux/proc_fs.h>
#include <linux/rtnetlink.h>
#include <linux/firmware.h>
#include <asm/uaccess.h>
#include "common.h"
......@@ -707,6 +708,28 @@ static void bind_qsets(struct adapter *adap)
}
}
#define FW_FNAME "t3fw-%d.%d.bin"
static int upgrade_fw(struct adapter *adap)
{
int ret;
char buf[64];
const struct firmware *fw;
struct device *dev = &adap->pdev->dev;
snprintf(buf, sizeof(buf), FW_FNAME, FW_VERSION_MAJOR,
FW_VERSION_MINOR);
ret = request_firmware(&fw, buf, dev);
if (ret < 0) {
dev_err(dev, "could not upgrade firmware: unable to load %s\n",
buf);
return ret;
}
ret = t3_load_fw(adap, fw->data, fw->size);
release_firmware(fw);
return ret;
}
/**
* cxgb_up - enable the adapter
* @adapter: adapter being enabled
......@@ -723,6 +746,8 @@ static int cxgb_up(struct adapter *adap)
if (!(adap->flags & FULL_INIT_DONE)) {
err = t3_check_fw_version(adap);
if (err == -EINVAL)
err = upgrade_fw(adap);
if (err)
goto out;
......
......@@ -681,7 +681,8 @@ enum {
SF_ERASE_SECTOR = 0xd8, /* erase sector */
FW_FLASH_BOOT_ADDR = 0x70000, /* start address of FW in flash */
FW_VERS_ADDR = 0x77ffc /* flash address holding FW version */
FW_VERS_ADDR = 0x77ffc, /* flash address holding FW version */
FW_MIN_SIZE = 8 /* at least version and csum */
};
/**
......@@ -935,7 +936,7 @@ int t3_load_fw(struct adapter *adapter, const u8 *fw_data, unsigned int size)
const u32 *p = (const u32 *)fw_data;
int ret, addr, fw_sector = FW_FLASH_BOOT_ADDR >> 16;
if (size & 3)
if ((size & 3) || size < FW_MIN_SIZE)
return -EINVAL;
if (size > FW_VERS_ADDR + 8 - FW_FLASH_BOOT_ADDR)
return -EFBIG;
......
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