]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/net/igb/e1000_nvm.c
Merge tag 'v2.6.38' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[mv-sheeva.git] / drivers / net / igb / e1000_nvm.c
index d83b77fa403825e17d72a6605715f6fd35a2bf92..6b5cc2cc453de02e2ed8d66ace44f7983b5c5d14 100644 (file)
@@ -445,31 +445,112 @@ out:
 }
 
 /**
- *  igb_read_part_num - Read device part number
+ *  igb_read_part_string - Read device part number
  *  @hw: pointer to the HW structure
  *  @part_num: pointer to device part number
+ *  @part_num_size: size of part number buffer
  *
  *  Reads the product board assembly (PBA) number from the EEPROM and stores
  *  the value in part_num.
  **/
-s32 igb_read_part_num(struct e1000_hw *hw, u32 *part_num)
+s32 igb_read_part_string(struct e1000_hw *hw, u8 *part_num, u32 part_num_size)
 {
-       s32  ret_val;
+       s32 ret_val;
        u16 nvm_data;
+       u16 pointer;
+       u16 offset;
+       u16 length;
+
+       if (part_num == NULL) {
+               hw_dbg("PBA string buffer was null\n");
+               ret_val = E1000_ERR_INVALID_ARGUMENT;
+               goto out;
+       }
 
        ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_0, 1, &nvm_data);
        if (ret_val) {
                hw_dbg("NVM Read Error\n");
                goto out;
        }
-       *part_num = (u32)(nvm_data << 16);
 
-       ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_1, 1, &nvm_data);
+       ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_1, 1, &pointer);
+       if (ret_val) {
+               hw_dbg("NVM Read Error\n");
+               goto out;
+       }
+
+       /*
+        * if nvm_data is not ptr guard the PBA must be in legacy format which
+        * means pointer 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) {
+               hw_dbg("NVM PBA number is not stored as string\n");
+
+               /* we will need 11 characters to store the PBA */
+               if (part_num_size < 11) {
+                       hw_dbg("PBA string buffer too small\n");
+                       return E1000_ERR_NO_SPACE;
+               }
+
+               /* extract hex string from data and pointer */
+               part_num[0] = (nvm_data >> 12) & 0xF;
+               part_num[1] = (nvm_data >> 8) & 0xF;
+               part_num[2] = (nvm_data >> 4) & 0xF;
+               part_num[3] = nvm_data & 0xF;
+               part_num[4] = (pointer >> 12) & 0xF;
+               part_num[5] = (pointer >> 8) & 0xF;
+               part_num[6] = '-';
+               part_num[7] = 0;
+               part_num[8] = (pointer >> 4) & 0xF;
+               part_num[9] = pointer & 0xF;
+
+               /* put a null character on the end of our string */
+               part_num[10] = '\0';
+
+               /* switch all the data but the '-' to hex char */
+               for (offset = 0; offset < 10; offset++) {
+                       if (part_num[offset] < 0xA)
+                               part_num[offset] += '0';
+                       else if (part_num[offset] < 0x10)
+                               part_num[offset] += 'A' - 0xA;
+               }
+
+               goto out;
+       }
+
+       ret_val = hw->nvm.ops.read(hw, pointer, 1, &length);
        if (ret_val) {
                hw_dbg("NVM Read Error\n");
                goto out;
        }
-       *part_num |= nvm_data;
+
+       if (length == 0xFFFF || length == 0) {
+               hw_dbg("NVM PBA number section invalid length\n");
+               ret_val = E1000_ERR_NVM_PBA_SECTION;
+               goto out;
+       }
+       /* check if part_num buffer is big enough */
+       if (part_num_size < (((u32)length * 2) - 1)) {
+               hw_dbg("PBA string buffer too small\n");
+               ret_val = E1000_ERR_NO_SPACE;
+               goto out;
+       }
+
+       /* trim pba length from start of string */
+       pointer++;
+       length--;
+
+       for (offset = 0; offset < length; offset++) {
+               ret_val = hw->nvm.ops.read(hw, pointer + offset, 1, &nvm_data);
+               if (ret_val) {
+                       hw_dbg("NVM Read Error\n");
+                       goto out;
+               }
+               part_num[offset * 2] = (u8)(nvm_data >> 8);
+               part_num[(offset * 2) + 1] = (u8)(nvm_data & 0xFF);
+       }
+       part_num[offset * 2] = '\0';
 
 out:
        return ret_val;