Merge branch 'liquidio-fw-loading'
Rick Farrington says: ==================== liquidio: firmware loading 1. Allow host driver parameter to override auto-loaded firmware (in flash). 2. Verify version of firmware that is auto-loaded from flash. 3. Change value of fw_type module parameter to reflect default firmware image name that is loaded by host driver (in /sys/module/liquidio/...) ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
d958af3d14
|
@ -59,9 +59,9 @@ static int debug = -1;
|
||||||
module_param(debug, int, 0644);
|
module_param(debug, int, 0644);
|
||||||
MODULE_PARM_DESC(debug, "NETIF_MSG debug bits");
|
MODULE_PARM_DESC(debug, "NETIF_MSG debug bits");
|
||||||
|
|
||||||
static char fw_type[LIO_MAX_FW_TYPE_LEN] = LIO_FW_NAME_TYPE_NIC;
|
static char fw_type[LIO_MAX_FW_TYPE_LEN] = LIO_FW_NAME_TYPE_AUTO;
|
||||||
module_param_string(fw_type, fw_type, sizeof(fw_type), 0444);
|
module_param_string(fw_type, fw_type, sizeof(fw_type), 0444);
|
||||||
MODULE_PARM_DESC(fw_type, "Type of firmware to be loaded. Default \"nic\". Use \"none\" to load firmware from flash.");
|
MODULE_PARM_DESC(fw_type, "Type of firmware to be loaded (default is \"auto\"), which uses firmware in flash, if present, else loads \"nic\".");
|
||||||
|
|
||||||
static u32 console_bitmask;
|
static u32 console_bitmask;
|
||||||
module_param(console_bitmask, int, 0644);
|
module_param(console_bitmask, int, 0644);
|
||||||
|
@ -1115,10 +1115,10 @@ liquidio_probe(struct pci_dev *pdev,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool fw_type_is_none(void)
|
static bool fw_type_is_auto(void)
|
||||||
{
|
{
|
||||||
return strncmp(fw_type, LIO_FW_NAME_TYPE_NONE,
|
return strncmp(fw_type, LIO_FW_NAME_TYPE_AUTO,
|
||||||
sizeof(LIO_FW_NAME_TYPE_NONE)) == 0;
|
sizeof(LIO_FW_NAME_TYPE_AUTO)) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1302,7 +1302,7 @@ static void octeon_destroy_resources(struct octeon_device *oct)
|
||||||
* Implementation note: only soft-reset the device
|
* Implementation note: only soft-reset the device
|
||||||
* if it is a CN6XXX OR the LAST CN23XX device.
|
* if it is a CN6XXX OR the LAST CN23XX device.
|
||||||
*/
|
*/
|
||||||
if (fw_type_is_none())
|
if (atomic_read(oct->adapter_fw_state) == FW_IS_PRELOADED)
|
||||||
octeon_pci_flr(oct);
|
octeon_pci_flr(oct);
|
||||||
else if (OCTEON_CN6XXX(oct) || !refcount)
|
else if (OCTEON_CN6XXX(oct) || !refcount)
|
||||||
oct->fn_list.soft_reset(oct);
|
oct->fn_list.soft_reset(oct);
|
||||||
|
@ -1934,10 +1934,12 @@ static int load_firmware(struct octeon_device *oct)
|
||||||
char fw_name[LIO_MAX_FW_FILENAME_LEN];
|
char fw_name[LIO_MAX_FW_FILENAME_LEN];
|
||||||
char *tmp_fw_type;
|
char *tmp_fw_type;
|
||||||
|
|
||||||
if (fw_type[0] == '\0')
|
if (fw_type_is_auto()) {
|
||||||
tmp_fw_type = LIO_FW_NAME_TYPE_NIC;
|
tmp_fw_type = LIO_FW_NAME_TYPE_NIC;
|
||||||
else
|
strncpy(fw_type, tmp_fw_type, sizeof(fw_type));
|
||||||
|
} else {
|
||||||
tmp_fw_type = fw_type;
|
tmp_fw_type = fw_type;
|
||||||
|
}
|
||||||
|
|
||||||
sprintf(fw_name, "%s%s%s_%s%s", LIO_FW_DIR, LIO_FW_BASE_NAME,
|
sprintf(fw_name, "%s%s%s_%s%s", LIO_FW_DIR, LIO_FW_BASE_NAME,
|
||||||
octeon_get_conf(oct)->card_name, tmp_fw_type,
|
octeon_get_conf(oct)->card_name, tmp_fw_type,
|
||||||
|
@ -3303,7 +3305,7 @@ static int setup_nic_devices(struct octeon_device *octeon_dev)
|
||||||
{
|
{
|
||||||
struct lio *lio = NULL;
|
struct lio *lio = NULL;
|
||||||
struct net_device *netdev;
|
struct net_device *netdev;
|
||||||
u8 mac[6], i, j;
|
u8 mac[6], i, j, *fw_ver;
|
||||||
struct octeon_soft_command *sc;
|
struct octeon_soft_command *sc;
|
||||||
struct liquidio_if_cfg_context *ctx;
|
struct liquidio_if_cfg_context *ctx;
|
||||||
struct liquidio_if_cfg_resp *resp;
|
struct liquidio_if_cfg_resp *resp;
|
||||||
|
@ -3414,6 +3416,22 @@ static int setup_nic_devices(struct octeon_device *octeon_dev)
|
||||||
goto setup_nic_dev_fail;
|
goto setup_nic_dev_fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Verify f/w version (in case of 'auto' loading from flash) */
|
||||||
|
fw_ver = octeon_dev->fw_info.liquidio_firmware_version;
|
||||||
|
if (memcmp(LIQUIDIO_BASE_VERSION,
|
||||||
|
fw_ver,
|
||||||
|
strlen(LIQUIDIO_BASE_VERSION))) {
|
||||||
|
dev_err(&octeon_dev->pci_dev->dev,
|
||||||
|
"Unmatched firmware version. Expected %s.x, got %s.\n",
|
||||||
|
LIQUIDIO_BASE_VERSION, fw_ver);
|
||||||
|
goto setup_nic_dev_fail;
|
||||||
|
} else if (atomic_read(octeon_dev->adapter_fw_state) ==
|
||||||
|
FW_IS_PRELOADED) {
|
||||||
|
dev_info(&octeon_dev->pci_dev->dev,
|
||||||
|
"Using auto-loaded firmware version %s.\n",
|
||||||
|
fw_ver);
|
||||||
|
}
|
||||||
|
|
||||||
octeon_swap_8B_data((u64 *)(&resp->cfg_info),
|
octeon_swap_8B_data((u64 *)(&resp->cfg_info),
|
||||||
(sizeof(struct liquidio_if_cfg_info)) >> 3);
|
(sizeof(struct liquidio_if_cfg_info)) >> 3);
|
||||||
|
|
||||||
|
@ -3882,9 +3900,9 @@ octeon_recv_vf_drv_notice(struct octeon_recv_info *recv_info, void *buf)
|
||||||
static int octeon_device_init(struct octeon_device *octeon_dev)
|
static int octeon_device_init(struct octeon_device *octeon_dev)
|
||||||
{
|
{
|
||||||
int j, ret;
|
int j, ret;
|
||||||
int fw_loaded = 0;
|
|
||||||
char bootcmd[] = "\n";
|
char bootcmd[] = "\n";
|
||||||
char *dbg_enb = NULL;
|
char *dbg_enb = NULL;
|
||||||
|
enum lio_fw_state fw_state;
|
||||||
struct octeon_device_priv *oct_priv =
|
struct octeon_device_priv *oct_priv =
|
||||||
(struct octeon_device_priv *)octeon_dev->priv;
|
(struct octeon_device_priv *)octeon_dev->priv;
|
||||||
atomic_set(&octeon_dev->status, OCT_DEV_BEGIN_STATE);
|
atomic_set(&octeon_dev->status, OCT_DEV_BEGIN_STATE);
|
||||||
|
@ -3916,24 +3934,40 @@ static int octeon_device_init(struct octeon_device *octeon_dev)
|
||||||
|
|
||||||
octeon_dev->app_mode = CVM_DRV_INVALID_APP;
|
octeon_dev->app_mode = CVM_DRV_INVALID_APP;
|
||||||
|
|
||||||
if (OCTEON_CN23XX_PF(octeon_dev)) {
|
/* CN23XX supports preloaded firmware if the following is true:
|
||||||
if (!cn23xx_fw_loaded(octeon_dev) && !fw_type_is_none()) {
|
*
|
||||||
fw_loaded = 0;
|
* The adapter indicates that firmware is currently running AND
|
||||||
/* Do a soft reset of the Octeon device. */
|
* 'fw_type' is 'auto'.
|
||||||
if (octeon_dev->fn_list.soft_reset(octeon_dev))
|
*
|
||||||
return 1;
|
* (default state is NEEDS_TO_BE_LOADED, override it if appropriate).
|
||||||
/* things might have changed */
|
*/
|
||||||
if (!cn23xx_fw_loaded(octeon_dev))
|
if (OCTEON_CN23XX_PF(octeon_dev) &&
|
||||||
fw_loaded = 0;
|
cn23xx_fw_loaded(octeon_dev) && fw_type_is_auto()) {
|
||||||
else
|
atomic_cmpxchg(octeon_dev->adapter_fw_state,
|
||||||
fw_loaded = 1;
|
FW_NEEDS_TO_BE_LOADED, FW_IS_PRELOADED);
|
||||||
} else {
|
|
||||||
fw_loaded = 1;
|
|
||||||
}
|
|
||||||
} else if (octeon_dev->fn_list.soft_reset(octeon_dev)) {
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If loading firmware, only first device of adapter needs to do so. */
|
||||||
|
fw_state = atomic_cmpxchg(octeon_dev->adapter_fw_state,
|
||||||
|
FW_NEEDS_TO_BE_LOADED,
|
||||||
|
FW_IS_BEING_LOADED);
|
||||||
|
|
||||||
|
/* Here, [local variable] 'fw_state' is set to one of:
|
||||||
|
*
|
||||||
|
* FW_IS_PRELOADED: No firmware is to be loaded (see above)
|
||||||
|
* FW_NEEDS_TO_BE_LOADED: The driver's first instance will load
|
||||||
|
* firmware to the adapter.
|
||||||
|
* FW_IS_BEING_LOADED: The driver's second instance will not load
|
||||||
|
* firmware to the adapter.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Prior to f/w load, perform a soft reset of the Octeon device;
|
||||||
|
* if error resetting, return w/error.
|
||||||
|
*/
|
||||||
|
if (fw_state == FW_NEEDS_TO_BE_LOADED)
|
||||||
|
if (octeon_dev->fn_list.soft_reset(octeon_dev))
|
||||||
|
return 1;
|
||||||
|
|
||||||
/* Initialize the dispatch mechanism used to push packets arriving on
|
/* Initialize the dispatch mechanism used to push packets arriving on
|
||||||
* Octeon Output queues.
|
* Octeon Output queues.
|
||||||
*/
|
*/
|
||||||
|
@ -4063,7 +4097,7 @@ static int octeon_device_init(struct octeon_device *octeon_dev)
|
||||||
|
|
||||||
atomic_set(&octeon_dev->status, OCT_DEV_IO_QUEUES_DONE);
|
atomic_set(&octeon_dev->status, OCT_DEV_IO_QUEUES_DONE);
|
||||||
|
|
||||||
if ((!OCTEON_CN23XX_PF(octeon_dev)) || !fw_loaded) {
|
if (fw_state == FW_NEEDS_TO_BE_LOADED) {
|
||||||
dev_dbg(&octeon_dev->pci_dev->dev, "Waiting for DDR initialization...\n");
|
dev_dbg(&octeon_dev->pci_dev->dev, "Waiting for DDR initialization...\n");
|
||||||
if (!ddr_timeout) {
|
if (!ddr_timeout) {
|
||||||
dev_info(&octeon_dev->pci_dev->dev,
|
dev_info(&octeon_dev->pci_dev->dev,
|
||||||
|
@ -4125,6 +4159,8 @@ static int octeon_device_init(struct octeon_device *octeon_dev)
|
||||||
dev_err(&octeon_dev->pci_dev->dev, "Could not load firmware to board\n");
|
dev_err(&octeon_dev->pci_dev->dev, "Could not load firmware to board\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
atomic_set(octeon_dev->adapter_fw_state, FW_HAS_BEEN_LOADED);
|
||||||
}
|
}
|
||||||
|
|
||||||
handshake[octeon_dev->octeon_id].init_ok = 1;
|
handshake[octeon_dev->octeon_id].init_ok = 1;
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#define LIO_FW_BASE_NAME "lio_"
|
#define LIO_FW_BASE_NAME "lio_"
|
||||||
#define LIO_FW_NAME_SUFFIX ".bin"
|
#define LIO_FW_NAME_SUFFIX ".bin"
|
||||||
#define LIO_FW_NAME_TYPE_NIC "nic"
|
#define LIO_FW_NAME_TYPE_NIC "nic"
|
||||||
|
#define LIO_FW_NAME_TYPE_AUTO "auto"
|
||||||
#define LIO_FW_NAME_TYPE_NONE "none"
|
#define LIO_FW_NAME_TYPE_NONE "none"
|
||||||
#define LIO_MAX_FIRMWARE_VERSION_LEN 16
|
#define LIO_MAX_FIRMWARE_VERSION_LEN 16
|
||||||
|
|
||||||
|
|
|
@ -541,6 +541,7 @@ static char oct_dev_app_str[CVM_DRV_APP_COUNT + 1][32] = {
|
||||||
|
|
||||||
static struct octeon_device *octeon_device[MAX_OCTEON_DEVICES];
|
static struct octeon_device *octeon_device[MAX_OCTEON_DEVICES];
|
||||||
static atomic_t adapter_refcounts[MAX_OCTEON_DEVICES];
|
static atomic_t adapter_refcounts[MAX_OCTEON_DEVICES];
|
||||||
|
static atomic_t adapter_fw_states[MAX_OCTEON_DEVICES];
|
||||||
|
|
||||||
static u32 octeon_device_count;
|
static u32 octeon_device_count;
|
||||||
/* locks device array (i.e. octeon_device[]) */
|
/* locks device array (i.e. octeon_device[]) */
|
||||||
|
@ -770,6 +771,10 @@ int octeon_register_device(struct octeon_device *oct,
|
||||||
oct->adapter_refcount = &adapter_refcounts[oct->octeon_id];
|
oct->adapter_refcount = &adapter_refcounts[oct->octeon_id];
|
||||||
atomic_set(oct->adapter_refcount, 0);
|
atomic_set(oct->adapter_refcount, 0);
|
||||||
|
|
||||||
|
/* Like the reference count, the f/w state is shared 'per-adapter' */
|
||||||
|
oct->adapter_fw_state = &adapter_fw_states[oct->octeon_id];
|
||||||
|
atomic_set(oct->adapter_fw_state, FW_NEEDS_TO_BE_LOADED);
|
||||||
|
|
||||||
spin_lock(&octeon_devices_lock);
|
spin_lock(&octeon_devices_lock);
|
||||||
for (idx = (int)oct->octeon_id - 1; idx >= 0; idx--) {
|
for (idx = (int)oct->octeon_id - 1; idx >= 0; idx--) {
|
||||||
if (!octeon_device[idx]) {
|
if (!octeon_device[idx]) {
|
||||||
|
@ -780,11 +785,15 @@ int octeon_register_device(struct octeon_device *oct,
|
||||||
atomic_inc(oct->adapter_refcount);
|
atomic_inc(oct->adapter_refcount);
|
||||||
return 1; /* here, refcount is guaranteed to be 1 */
|
return 1; /* here, refcount is guaranteed to be 1 */
|
||||||
}
|
}
|
||||||
/* if another device is at same bus/dev, use its refcounter */
|
/* If another device is at same bus/dev, use its refcounter
|
||||||
|
* (and f/w state variable).
|
||||||
|
*/
|
||||||
if ((octeon_device[idx]->loc.bus == bus) &&
|
if ((octeon_device[idx]->loc.bus == bus) &&
|
||||||
(octeon_device[idx]->loc.dev == dev)) {
|
(octeon_device[idx]->loc.dev == dev)) {
|
||||||
oct->adapter_refcount =
|
oct->adapter_refcount =
|
||||||
octeon_device[idx]->adapter_refcount;
|
octeon_device[idx]->adapter_refcount;
|
||||||
|
oct->adapter_fw_state =
|
||||||
|
octeon_device[idx]->adapter_fw_state;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,6 +50,13 @@ enum octeon_pci_swap_mode {
|
||||||
OCTEON_PCI_32BIT_LW_SWAP = 3
|
OCTEON_PCI_32BIT_LW_SWAP = 3
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum lio_fw_state {
|
||||||
|
FW_IS_PRELOADED = 0,
|
||||||
|
FW_NEEDS_TO_BE_LOADED = 1,
|
||||||
|
FW_IS_BEING_LOADED = 2,
|
||||||
|
FW_HAS_BEEN_LOADED = 3,
|
||||||
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
OCTEON_CONFIG_TYPE_DEFAULT = 0,
|
OCTEON_CONFIG_TYPE_DEFAULT = 0,
|
||||||
NUM_OCTEON_CONFS,
|
NUM_OCTEON_CONFS,
|
||||||
|
@ -557,6 +564,9 @@ struct octeon_device {
|
||||||
} loc;
|
} loc;
|
||||||
|
|
||||||
atomic_t *adapter_refcount; /* reference count of adapter */
|
atomic_t *adapter_refcount; /* reference count of adapter */
|
||||||
|
|
||||||
|
atomic_t *adapter_fw_state; /* per-adapter, lio_fw_state */
|
||||||
|
|
||||||
bool ptp_enable;
|
bool ptp_enable;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue