i40e: Change the ethtool NVM read method to use AQ
authorAnjali Singhai Jain <anjali.singhai@intel.com>
Thu, 28 Nov 2013 06:39:28 +0000 (06:39 +0000)
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>
Sun, 5 Jan 2014 06:22:26 +0000 (22:22 -0800)
Earlier we were reading Shadow RAM (copy of the NVM) which can differ
from the actual NVM. Use AQ instead to read the actual NVM.

Change-Id: Ia0f2773b722db77d093f738c068af872be69bbd4
Signed-off-by: Anjali Singhai Jain <anjali.singhai@intel.com>
Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
Tested-by: Kavindya Deegala <kavindya.s.deegala@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
drivers/net/ethernet/intel/i40e/i40e_ethtool.c

index 0359c36b86cc1b1603f6503209834f2e67070144..42c36d18e8c66fe9e515d0231eaedc845db342a3 100644 (file)
@@ -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;
-
-       return hw->nvm.sr_size * 2;
+       u32 val;
+
+       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,