diff options
Diffstat (limited to 'drivers/net/ethernet/intel/i40e/i40e_ethtool.c')
-rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 71 |
1 files changed, 66 insertions, 5 deletions
diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index 3abd3cbab75f..9c93ff28d4aa 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -630,7 +630,7 @@ static int i40e_set_pauseparam(struct net_device *netdev, bool link_up = hw_link_info->link_info & I40E_AQ_LINK_UP; i40e_status status; u8 aq_failures; - int err; + int err = 0; if (vsi != pf->vsi[pf->lan_vsi]) return -EOPNOTSUPP; @@ -683,8 +683,12 @@ static int i40e_set_pauseparam(struct net_device *netdev, err = -EAGAIN; } - if (!test_bit(__I40E_DOWN, &pf->state)) - return i40e_nway_reset(netdev); + if (!test_bit(__I40E_DOWN, &pf->state)) { + /* Give it a little more time to try to come back */ + msleep(75); + if (!test_bit(__I40E_DOWN, &pf->state)) + return i40e_nway_reset(netdev); + } return err; } @@ -759,10 +763,33 @@ static int i40e_get_eeprom(struct net_device *netdev, u8 *eeprom_buff; u16 i, sectors; bool last; + u32 magic; + #define I40E_NVM_SECTOR_SIZE 4096 if (eeprom->len == 0) return -EINVAL; + /* check for NVMUpdate access method */ + magic = hw->vendor_id | (hw->device_id << 16); + if (eeprom->magic && eeprom->magic != magic) { + int errno; + + /* make sure it is the right magic for NVMUpdate */ + if ((eeprom->magic >> 16) != hw->device_id) + return -EINVAL; + + ret_val = i40e_nvmupd_command(hw, + (struct i40e_nvm_access *)eeprom, + bytes, &errno); + if (ret_val) + dev_info(&pf->pdev->dev, + "NVMUpdate read failed err=%d status=0x%x\n", + ret_val, hw->aq.asq_last_status); + + return errno; + } + + /* normal ethtool get_eeprom support */ eeprom->magic = hw->vendor_id | (hw->device_id << 16); eeprom_buff = kzalloc(eeprom->len, GFP_KERNEL); @@ -789,7 +816,7 @@ static int i40e_get_eeprom(struct net_device *netdev, ret_val = i40e_aq_read_nvm(hw, 0x0, eeprom->offset + (I40E_NVM_SECTOR_SIZE * i), len, - eeprom_buff + (I40E_NVM_SECTOR_SIZE * i), + (u8 *)eeprom_buff + (I40E_NVM_SECTOR_SIZE * i), last, NULL); if (ret_val) { dev_info(&pf->pdev->dev, @@ -801,7 +828,7 @@ static int i40e_get_eeprom(struct net_device *netdev, release_nvm: i40e_release_nvm(hw); - memcpy(bytes, eeprom_buff, eeprom->len); + memcpy(bytes, (u8 *)eeprom_buff, eeprom->len); free_buff: kfree(eeprom_buff); return ret_val; @@ -821,6 +848,39 @@ static int i40e_get_eeprom_len(struct net_device *netdev) return val; } +static int i40e_set_eeprom(struct net_device *netdev, + struct ethtool_eeprom *eeprom, u8 *bytes) +{ + struct i40e_netdev_priv *np = netdev_priv(netdev); + struct i40e_hw *hw = &np->vsi->back->hw; + struct i40e_pf *pf = np->vsi->back; + int ret_val = 0; + int errno; + u32 magic; + + /* normal ethtool set_eeprom is not supported */ + magic = hw->vendor_id | (hw->device_id << 16); + if (eeprom->magic == magic) + return -EOPNOTSUPP; + + /* check for NVMUpdate access method */ + if (!eeprom->magic || (eeprom->magic >> 16) != hw->device_id) + return -EINVAL; + + if (test_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state) || + test_bit(__I40E_RESET_INTR_RECEIVED, &pf->state)) + return -EBUSY; + + ret_val = i40e_nvmupd_command(hw, (struct i40e_nvm_access *)eeprom, + bytes, &errno); + if (ret_val) + dev_info(&pf->pdev->dev, + "NVMUpdate write failed err=%d status=0x%x\n", + ret_val, hw->aq.asq_last_status); + + return errno; +} + static void i40e_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo) { @@ -2094,6 +2154,7 @@ static const struct ethtool_ops i40e_ethtool_ops = { .get_link = ethtool_op_get_link, .get_wol = i40e_get_wol, .set_wol = i40e_set_wol, + .set_eeprom = i40e_set_eeprom, .get_eeprom_len = i40e_get_eeprom_len, .get_eeprom = i40e_get_eeprom, .get_ringparam = i40e_get_ringparam, |