@ -239,6 +239,7 @@ struct myri10ge_priv {
int watchdog_resets ;
int watchdog_pause ;
int pause ;
bool fw_name_allocated ;
char * fw_name ;
char eeprom_strings [ MYRI10GE_EEPROM_STRINGS_SIZE ] ;
char * product_code_string ;
@ -271,6 +272,7 @@ MODULE_FIRMWARE("myri10ge_eth_z8e.dat");
MODULE_FIRMWARE ( " myri10ge_rss_ethp_z8e.dat " ) ;
MODULE_FIRMWARE ( " myri10ge_rss_eth_z8e.dat " ) ;
/* Careful: must be accessed under kparam_block_sysfs_write */
static char * myri10ge_fw_name = NULL ;
module_param ( myri10ge_fw_name , charp , S_IRUGO | S_IWUSR ) ;
MODULE_PARM_DESC ( myri10ge_fw_name , " Firmware image name " ) ;
@ -376,6 +378,14 @@ static inline void put_be32(__be32 val, __be32 __iomem * p)
static struct net_device_stats * myri10ge_get_stats ( struct net_device * dev ) ;
static void set_fw_name ( struct myri10ge_priv * mgp , char * name , bool allocated )
{
if ( mgp - > fw_name_allocated )
kfree ( mgp - > fw_name ) ;
mgp - > fw_name = name ;
mgp - > fw_name_allocated = allocated ;
}
static int
myri10ge_send_cmd ( struct myri10ge_priv * mgp , u32 cmd ,
struct myri10ge_cmd * data , int atomic )
@ -747,7 +757,7 @@ static int myri10ge_load_firmware(struct myri10ge_priv *mgp, int adopt)
dev_warn ( & mgp - > pdev - > dev , " via hotplug \n " ) ;
}
mgp - > fw_name = " adopted " ;
set_fw_name ( mgp , " adopted " , false ) ;
mgp - > tx_boundary = 2048 ;
myri10ge_dummy_rdma ( mgp , 1 ) ;
status = myri10ge_get_firmware_capabilities ( mgp ) ;
@ -3233,7 +3243,7 @@ static void myri10ge_firmware_probe(struct myri10ge_priv *mgp)
* load the optimized firmware ( which assumes aligned PCIe
* completions ) in order to see if it works on this host .
*/
mgp - > fw_name = myri10ge_fw_aligned ;
set_fw_name ( mgp , myri10ge_fw_aligned , false ) ;
status = myri10ge_load_firmware ( mgp , 1 ) ;
if ( status ! = 0 ) {
goto abort ;
@ -3261,7 +3271,7 @@ static void myri10ge_firmware_probe(struct myri10ge_priv *mgp)
abort :
/* fall back to using the unaligned firmware */
mgp - > tx_boundary = 2048 ;
mgp - > fw_name = myri10ge_fw_unaligned ;
set_fw_name ( mgp , myri10ge_fw_unaligned , false ) ;
}
@ -3284,7 +3294,7 @@ static void myri10ge_select_firmware(struct myri10ge_priv *mgp)
dev_info ( & mgp - > pdev - > dev , " PCIE x%d Link \n " ,
link_width ) ;
mgp - > tx_boundary = 4096 ;
mgp - > fw_name = myri10ge_fw_aligned ;
set_fw_name ( mgp , myri10ge_fw_aligned , false ) ;
} else {
myri10ge_firmware_probe ( mgp ) ;
}
@ -3293,22 +3303,29 @@ static void myri10ge_select_firmware(struct myri10ge_priv *mgp)
dev_info ( & mgp - > pdev - > dev ,
" Assuming aligned completions (forced) \n " ) ;
mgp - > tx_boundary = 4096 ;
mgp - > fw_name = myri10ge_fw_aligned ;
set_fw_name ( mgp , myri10ge_fw_aligned , false ) ;
} else {
dev_info ( & mgp - > pdev - > dev ,
" Assuming unaligned completions (forced) \n " ) ;
mgp - > tx_boundary = 2048 ;
mgp - > fw_name = myri10ge_fw_unaligned ;
set_fw_name ( mgp , myri10ge_fw_unaligned , false ) ;
}
}
kparam_block_sysfs_write ( myri10ge_fw_name ) ;
if ( myri10ge_fw_name ! = NULL ) {
overridden = 1 ;
mgp - > fw_name = myri10ge_fw_name ;
char * fw_name = kstrdup ( myri10ge_fw_name , GFP_KERNEL ) ;
if ( fw_name ) {
overridden = 1 ;
set_fw_name ( mgp , fw_name , true ) ;
}
}
kparam_unblock_sysfs_write ( myri10ge_fw_name ) ;
if ( mgp - > board_number < MYRI10GE_MAX_BOARDS & &
myri10ge_fw_names [ mgp - > board_number ] ! = NULL & &
strlen ( myri10ge_fw_names [ mgp - > board_number ] ) ) {
mgp - > fw_name = myri10ge_fw_names [ mgp - > board_number ] ;
set_fw_name ( mgp , myri10ge_fw_names [ mgp - > board_number ] , false ) ;
overridden = 1 ;
}
if ( overridden )
@ -3660,6 +3677,7 @@ static void myri10ge_probe_slices(struct myri10ge_priv *mgp)
struct myri10ge_cmd cmd ;
struct pci_dev * pdev = mgp - > pdev ;
char * old_fw ;
bool old_allocated ;
int i , status , ncpus , msix_cap ;
mgp - > num_slices = 1 ;
@ -3672,17 +3690,23 @@ static void myri10ge_probe_slices(struct myri10ge_priv *mgp)
/* try to load the slice aware rss firmware */
old_fw = mgp - > fw_name ;
old_allocated = mgp - > fw_name_allocated ;
/* don't free old_fw if we override it. */
mgp - > fw_name_allocated = false ;
if ( myri10ge_fw_name ! = NULL ) {
dev_info ( & mgp - > pdev - > dev , " overriding rss firmware to %s \n " ,
myri10ge_fw_name ) ;
mgp - > fw_name = myri10ge_fw_name ;
set_fw_name ( mgp , myri10ge_fw_name , false ) ;
} else if ( old_fw = = myri10ge_fw_aligned )
mgp - > fw_name = myri10ge_fw_rss_aligned ;
set_fw_name ( mgp , myri10ge_fw_rss_aligned , false ) ;
else
mgp - > fw_name = myri10ge_fw_rss_unaligned ;
set_fw_name ( mgp , myri10ge_fw_rss_unaligned , false ) ;
status = myri10ge_load_firmware ( mgp , 0 ) ;
if ( status ! = 0 ) {
dev_info ( & pdev - > dev , " Rss firmware not found \n " ) ;
if ( old_allocated )
kfree ( old_fw ) ;
return ;
}
@ -3747,6 +3771,8 @@ static void myri10ge_probe_slices(struct myri10ge_priv *mgp)
mgp - > num_slices ) ;
if ( status = = 0 ) {
pci_disable_msix ( pdev ) ;
if ( old_allocated )
kfree ( old_fw ) ;
return ;
}
if ( status > 0 )
@ -3763,7 +3789,7 @@ disable_msix:
abort_with_fw :
mgp - > num_slices = 1 ;
mgp - > fw_name = old_fw ;
set_fw_name ( mgp , old_fw , old_allocated ) ;
myri10ge_load_firmware ( mgp , 0 ) ;
}
@ -3993,6 +4019,7 @@ abort_with_enabled:
pci_disable_device ( pdev ) ;
abort_with_netdev :
set_fw_name ( mgp , NULL , false ) ;
free_netdev ( netdev ) ;
return status ;
}
@ -4037,6 +4064,7 @@ static void myri10ge_remove(struct pci_dev *pdev)
dma_free_coherent ( & pdev - > dev , sizeof ( * mgp - > cmd ) ,
mgp - > cmd , mgp - > cmd_bus ) ;
set_fw_name ( mgp , NULL , false ) ;
free_netdev ( netdev ) ;
pci_disable_device ( pdev ) ;
pci_set_drvdata ( pdev , NULL ) ;