e1000e: support new PBA format from EEPROM
authorBruce Allan <bruce.w.allan@intel.com>
Wed, 24 Nov 2010 06:01:51 +0000 (06:01 +0000)
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>
Sat, 11 Dec 2010 06:13:37 +0000 (22:13 -0800)
Provide support to e1000e for displaying the new format of the PBA found
in the EEPROM.  The unique PBA identifier is no longer restricted to
hexadecimal numbers and must now be read and displayed as a string.

Signed-off-by: Bruce Allan <bruce.w.allan@intel.com>
Tested-by: Jeff Pieper <jeffrey.e.pieper@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
drivers/net/e1000e/defines.h
drivers/net/e1000e/e1000.h
drivers/net/e1000e/lib.c
drivers/net/e1000e/netdev.c

index 016ea383145add5f9c20a28524c6d3acb8c6e21f..7245dc2e0b7cc0d1d73aa84fa36378cc94f3db59 100644 (file)
 #define E1000_BLK_PHY_RESET   12
 #define E1000_ERR_SWFW_SYNC 13
 #define E1000_NOT_IMPLEMENTED 14
+#define E1000_ERR_INVALID_ARGUMENT  16
+#define E1000_ERR_NO_SPACE          17
+#define E1000_ERR_NVM_PBA_SECTION   18
 
 /* Loop limit on how long we wait for auto-negotiation to complete */
 #define FIBER_LINK_UP_LIMIT               50
 /* Mask bits for fields in Word 0x03 of the EEPROM */
 #define NVM_COMPAT_LOM    0x0800
 
+/* length of string needed to store PBA number */
+#define E1000_PBANUM_LENGTH             11
+
 /* For checksumming, the sum of all words in the NVM should equal 0xBABA. */
 #define NVM_SUM                    0xBABA
 
 /* PBA (printed board assembly) number words */
 #define NVM_PBA_OFFSET_0           8
 #define NVM_PBA_OFFSET_1           9
-
+#define NVM_PBA_PTR_GUARD          0xFAFA
 #define NVM_WORD_SIZE_BASE_SHIFT   6
 
 /* NVM Commands - SPI */
index 3d9366ffd16edffbea9d9e6cdd0f97c9be790f66..2c913b8e91165d9f53e0915a0c074d94625713a7 100644 (file)
@@ -514,7 +514,8 @@ extern struct e1000_info e1000_pch_info;
 extern struct e1000_info e1000_pch2_info;
 extern struct e1000_info e1000_es2_info;
 
-extern s32 e1000e_read_pba_num(struct e1000_hw *hw, u32 *pba_num);
+extern s32 e1000_read_pba_string_generic(struct e1000_hw *hw, u8 *pba_num,
+                                        u32 pba_num_size);
 
 extern s32  e1000e_commit_phy(struct e1000_hw *hw);
 
index 0fd4eb5ac5fb9241f57061ee5eb76dff06e8afbf..8377523c054a630ec95f09d56cdf2134be9dff37 100644 (file)
@@ -2138,6 +2138,119 @@ s32 e1000e_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
        return 0;
 }
 
+/**
+ *  e1000_read_pba_string_generic - Read device part number
+ *  @hw: pointer to the HW structure
+ *  @pba_num: pointer to device part number
+ *  @pba_num_size: size of part number buffer
+ *
+ *  Reads the product board assembly (PBA) number from the EEPROM and stores
+ *  the value in pba_num.
+ **/
+s32 e1000_read_pba_string_generic(struct e1000_hw *hw, u8 *pba_num,
+                                 u32 pba_num_size)
+{
+       s32 ret_val;
+       u16 nvm_data;
+       u16 pba_ptr;
+       u16 offset;
+       u16 length;
+
+       if (pba_num == NULL) {
+               e_dbg("PBA string buffer was null\n");
+               ret_val = E1000_ERR_INVALID_ARGUMENT;
+               goto out;
+       }
+
+       ret_val = e1000_read_nvm(hw, NVM_PBA_OFFSET_0, 1, &nvm_data);
+       if (ret_val) {
+               e_dbg("NVM Read Error\n");
+               goto out;
+       }
+
+       ret_val = e1000_read_nvm(hw, NVM_PBA_OFFSET_1, 1, &pba_ptr);
+       if (ret_val) {
+               e_dbg("NVM Read Error\n");
+               goto out;
+       }
+
+       /*
+        * if nvm_data is not ptr guard the PBA must be in legacy format which
+        * means pba_ptr is actually our second data word for the PBA number
+        * and we can decode it into an ascii string
+        */
+       if (nvm_data != NVM_PBA_PTR_GUARD) {
+               e_dbg("NVM PBA number is not stored as string\n");
+
+               /* we will need 11 characters to store the PBA */
+               if (pba_num_size < 11) {
+                       e_dbg("PBA string buffer too small\n");
+                       return E1000_ERR_NO_SPACE;
+               }
+
+               /* extract hex string from data and pba_ptr */
+               pba_num[0] = (nvm_data >> 12) & 0xF;
+               pba_num[1] = (nvm_data >> 8) & 0xF;
+               pba_num[2] = (nvm_data >> 4) & 0xF;
+               pba_num[3] = nvm_data & 0xF;
+               pba_num[4] = (pba_ptr >> 12) & 0xF;
+               pba_num[5] = (pba_ptr >> 8) & 0xF;
+               pba_num[6] = '-';
+               pba_num[7] = 0;
+               pba_num[8] = (pba_ptr >> 4) & 0xF;
+               pba_num[9] = pba_ptr & 0xF;
+
+               /* put a null character on the end of our string */
+               pba_num[10] = '\0';
+
+               /* switch all the data but the '-' to hex char */
+               for (offset = 0; offset < 10; offset++) {
+                       if (pba_num[offset] < 0xA)
+                               pba_num[offset] += '0';
+                       else if (pba_num[offset] < 0x10)
+                               pba_num[offset] += 'A' - 0xA;
+               }
+
+               goto out;
+       }
+
+       ret_val = e1000_read_nvm(hw, pba_ptr, 1, &length);
+       if (ret_val) {
+               e_dbg("NVM Read Error\n");
+               goto out;
+       }
+
+       if (length == 0xFFFF || length == 0) {
+               e_dbg("NVM PBA number section invalid length\n");
+               ret_val = E1000_ERR_NVM_PBA_SECTION;
+               goto out;
+       }
+       /* check if pba_num buffer is big enough */
+       if (pba_num_size < (((u32)length * 2) - 1)) {
+               e_dbg("PBA string buffer too small\n");
+               ret_val = E1000_ERR_NO_SPACE;
+               goto out;
+       }
+
+       /* trim pba length from start of string */
+       pba_ptr++;
+       length--;
+
+       for (offset = 0; offset < length; offset++) {
+               ret_val = e1000_read_nvm(hw, pba_ptr + offset, 1, &nvm_data);
+               if (ret_val) {
+                       e_dbg("NVM Read Error\n");
+                       goto out;
+               }
+               pba_num[offset * 2] = (u8)(nvm_data >> 8);
+               pba_num[(offset * 2) + 1] = (u8)(nvm_data & 0xFF);
+       }
+       pba_num[offset * 2] = '\0';
+
+out:
+       return ret_val;
+}
+
 /**
  *  e1000_read_mac_addr_generic - Read device MAC address
  *  @hw: pointer to the HW structure
@@ -2579,25 +2692,3 @@ bool e1000e_enable_mng_pass_thru(struct e1000_hw *hw)
 out:
        return ret_val;
 }
-
-s32 e1000e_read_pba_num(struct e1000_hw *hw, u32 *pba_num)
-{
-       s32 ret_val;
-       u16 nvm_data;
-
-       ret_val = e1000_read_nvm(hw, NVM_PBA_OFFSET_0, 1, &nvm_data);
-       if (ret_val) {
-               e_dbg("NVM Read Error\n");
-               return ret_val;
-       }
-       *pba_num = (u32)(nvm_data << 16);
-
-       ret_val = e1000_read_nvm(hw, NVM_PBA_OFFSET_1, 1, &nvm_data);
-       if (ret_val) {
-               e_dbg("NVM Read Error\n");
-               return ret_val;
-       }
-       *pba_num |= nvm_data;
-
-       return 0;
-}
index f8efbbbfddfbb99018a469f1b8a229c72e352645..393b76d27536eb735caaa92ae920827cf90c90ae 100644 (file)
@@ -5626,7 +5626,8 @@ static void e1000_print_device_info(struct e1000_adapter *adapter)
 {
        struct e1000_hw *hw = &adapter->hw;
        struct net_device *netdev = adapter->netdev;
-       u32 pba_num;
+       u32 ret_val;
+       u8 pba_str[E1000_PBANUM_LENGTH];
 
        /* print bus type/speed/width info */
        e_info("(PCI Express:2.5GB/s:%s) %pM\n",
@@ -5637,9 +5638,12 @@ static void e1000_print_device_info(struct e1000_adapter *adapter)
               netdev->dev_addr);
        e_info("Intel(R) PRO/%s Network Connection\n",
               (hw->phy.type == e1000_phy_ife) ? "10/100" : "1000");
-       e1000e_read_pba_num(hw, &pba_num);
-       e_info("MAC: %d, PHY: %d, PBA No: %06x-%03x\n",
-              hw->mac.type, hw->phy.type, (pba_num >> 8), (pba_num & 0xff));
+       ret_val = e1000_read_pba_string_generic(hw, pba_str,
+                                               E1000_PBANUM_LENGTH);
+       if (ret_val)
+               strcpy(pba_str, "Unknown");
+       e_info("MAC: %d, PHY: %d, PBA No: %s\n",
+              hw->mac.type, hw->phy.type, pba_str);
 }
 
 static void e1000_eeprom_checks(struct e1000_adapter *adapter)