diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index 0359c36b86cc..42c36d18e8c6 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -351,38 +351,56 @@ static int i40e_get_eeprom(struct net_device *netdev, { struct i40e_netdev_priv *np = netdev_priv(netdev); struct i40e_hw *hw = &np->vsi->back->hw; - int first_word, last_word; - u16 i, eeprom_len; - u16 *eeprom_buff; - int ret_val = 0; - + struct i40e_pf *pf = np->vsi->back; + int ret_val = 0, len; + u8 *eeprom_buff; + u16 i, sectors; + bool last; +#define I40E_NVM_SECTOR_SIZE 4096 if (eeprom->len == 0) return -EINVAL; eeprom->magic = hw->vendor_id | (hw->device_id << 16); - first_word = eeprom->offset >> 1; - last_word = (eeprom->offset + eeprom->len - 1) >> 1; - eeprom_len = last_word - first_word + 1; - - eeprom_buff = kmalloc(sizeof(u16) * eeprom_len, GFP_KERNEL); + eeprom_buff = kzalloc(eeprom->len, GFP_KERNEL); if (!eeprom_buff) return -ENOMEM; - ret_val = i40e_read_nvm_buffer(hw, first_word, &eeprom_len, - eeprom_buff); - if (eeprom_len == 0) { - kfree(eeprom_buff); - return -EACCES; + ret_val = i40e_acquire_nvm(hw, I40E_RESOURCE_READ); + if (ret_val) { + dev_info(&pf->pdev->dev, + "Failed Acquiring NVM resource for read err=%d status=0x%x\n", + ret_val, hw->aq.asq_last_status); + goto free_buff; } - /* Device's eeprom is always little-endian, word addressable */ - for (i = 0; i < eeprom_len; i++) - le16_to_cpus(&eeprom_buff[i]); + sectors = eeprom->len / I40E_NVM_SECTOR_SIZE; + sectors += (eeprom->len % I40E_NVM_SECTOR_SIZE) ? 1 : 0; + len = I40E_NVM_SECTOR_SIZE; + last = false; + for (i = 0; i < sectors; i++) { + if (i == (sectors - 1)) { + len = eeprom->len - (I40E_NVM_SECTOR_SIZE * i); + last = true; + } + ret_val = i40e_aq_read_nvm(hw, 0x0, + eeprom->offset + (I40E_NVM_SECTOR_SIZE * i), + len, + (u8 *)eeprom_buff + (I40E_NVM_SECTOR_SIZE * i), + last, NULL); + if (ret_val) { + dev_info(&pf->pdev->dev, + "read NVM failed err=%d status=0x%x\n", + ret_val, hw->aq.asq_last_status); + goto release_nvm; + } + } - memcpy(bytes, (u8 *)eeprom_buff + (eeprom->offset & 1), eeprom->len); +release_nvm: + i40e_release_nvm(hw); + memcpy(bytes, (u8 *)eeprom_buff, eeprom->len); +free_buff: kfree(eeprom_buff); - return ret_val; } @@ -390,8 +408,14 @@ static int i40e_get_eeprom_len(struct net_device *netdev) { struct i40e_netdev_priv *np = netdev_priv(netdev); struct i40e_hw *hw = &np->vsi->back->hw; + u32 val; - return hw->nvm.sr_size * 2; + val = (rd32(hw, I40E_GLPCI_LBARCTRL) + & I40E_GLPCI_LBARCTRL_FL_SIZE_MASK) + >> I40E_GLPCI_LBARCTRL_FL_SIZE_SHIFT; + /* register returns value in power of 2, 64Kbyte chunks. */ + val = (64 * 1024) * (1 << val); + return val; } static void i40e_get_drvinfo(struct net_device *netdev,