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 ...@@ -2374,6 +2374,7 @@ config CHELSIO_T1_NAPI
config CHELSIO_T3 config CHELSIO_T3
tristate "Chelsio Communications T3 10Gb Ethernet support" tristate "Chelsio Communications T3 10Gb Ethernet support"
depends on PCI depends on PCI
select FW_LOADER
help help
This driver supports Chelsio T3-based gigabit and 10Gb Ethernet This driver supports Chelsio T3-based gigabit and 10Gb Ethernet
adapters. adapters.
......
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <linux/rtnetlink.h> #include <linux/rtnetlink.h>
#include <linux/firmware.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include "common.h" #include "common.h"
...@@ -707,6 +708,28 @@ static void bind_qsets(struct adapter *adap) ...@@ -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 * cxgb_up - enable the adapter
* @adapter: adapter being enabled * @adapter: adapter being enabled
...@@ -723,6 +746,8 @@ static int cxgb_up(struct adapter *adap) ...@@ -723,6 +746,8 @@ static int cxgb_up(struct adapter *adap)
if (!(adap->flags & FULL_INIT_DONE)) { if (!(adap->flags & FULL_INIT_DONE)) {
err = t3_check_fw_version(adap); err = t3_check_fw_version(adap);
if (err == -EINVAL)
err = upgrade_fw(adap);
if (err) if (err)
goto out; goto out;
......
...@@ -681,7 +681,8 @@ enum { ...@@ -681,7 +681,8 @@ enum {
SF_ERASE_SECTOR = 0xd8, /* erase sector */ SF_ERASE_SECTOR = 0xd8, /* erase sector */
FW_FLASH_BOOT_ADDR = 0x70000, /* start address of FW in flash */ 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) ...@@ -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; const u32 *p = (const u32 *)fw_data;
int ret, addr, fw_sector = FW_FLASH_BOOT_ADDR >> 16; int ret, addr, fw_sector = FW_FLASH_BOOT_ADDR >> 16;
if (size & 3) if ((size & 3) || size < FW_MIN_SIZE)
return -EINVAL; return -EINVAL;
if (size > FW_VERS_ADDR + 8 - FW_FLASH_BOOT_ADDR) if (size > FW_VERS_ADDR + 8 - FW_FLASH_BOOT_ADDR)
return -EFBIG; 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