]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/net/e1000e/ich8lan.c
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
[linux-2.6-omap-h63xx.git] / drivers / net / e1000e / ich8lan.c
index d115a6d30f29c0b3acb81c8038c6215993980e8d..f2a5963b5a9562f153391c4f2b8b364742736d1b 100644 (file)
@@ -27,6 +27,7 @@
 *******************************************************************************/
 
 /*
+ * 82562G 10/100 Network Connection
  * 82562G-2 10/100 Network Connection
  * 82562GT 10/100 Network Connection
  * 82562GT-2 10/100 Network Connection
@@ -40,6 +41,7 @@
  * 82566MM Gigabit Network Connection
  * 82567LM Gigabit Network Connection
  * 82567LF Gigabit Network Connection
+ * 82567V Gigabit Network Connection
  * 82567LM-2 Gigabit Network Connection
  * 82567LF-2 Gigabit Network Connection
  * 82567V-2 Gigabit Network Connection
@@ -92,6 +94,8 @@
 
 #define E1000_ICH_NVM_SIG_WORD         0x13
 #define E1000_ICH_NVM_SIG_MASK         0xC000
+#define E1000_ICH_NVM_VALID_SIG_MASK    0xC0
+#define E1000_ICH_NVM_SIG_VALUE         0x80
 
 #define E1000_ICH8_LAN_INIT_TIMEOUT    1500
 
@@ -956,45 +960,62 @@ static s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, bool active)
  *  @bank:  pointer to the variable that returns the active bank
  *
  *  Reads signature byte from the NVM using the flash access registers.
+ *  Word 0x13 bits 15:14 = 10b indicate a valid signature for that bank.
  **/
 static s32 e1000_valid_nvm_bank_detect_ich8lan(struct e1000_hw *hw, u32 *bank)
 {
+       u32 eecd;
        struct e1000_nvm_info *nvm = &hw->nvm;
-       /* flash bank size is in words */
        u32 bank1_offset = nvm->flash_bank_size * sizeof(u16);
        u32 act_offset = E1000_ICH_NVM_SIG_WORD * 2 + 1;
-       u8 bank_high_byte = 0;
+       u8 sig_byte = 0;
+       s32 ret_val = 0;
 
-       if (hw->mac.type != e1000_ich10lan) {
-               if (er32(EECD) & E1000_EECD_SEC1VAL)
-                       *bank = 1;
-               else
-                       *bank = 0;
-       } else {
-               /*
-                * Make sure the signature for bank 0 is valid,
-                * if not check for bank1
-                */
-               e1000_read_flash_byte_ich8lan(hw, act_offset, &bank_high_byte);
-               if ((bank_high_byte & 0xC0) == 0x80) {
+       switch (hw->mac.type) {
+       case e1000_ich8lan:
+       case e1000_ich9lan:
+               eecd = er32(EECD);
+               if ((eecd & E1000_EECD_SEC1VAL_VALID_MASK) ==
+                   E1000_EECD_SEC1VAL_VALID_MASK) {
+                       if (eecd & E1000_EECD_SEC1VAL)
+                               *bank = 1;
+                       else
+                               *bank = 0;
+
+                       return 0;
+               }
+               hw_dbg(hw, "Unable to determine valid NVM bank via EEC - "
+                      "reading flash signature\n");
+               /* fall-thru */
+       default:
+               /* set bank to 0 in case flash read fails */
+               *bank = 0;
+
+               /* Check bank 0 */
+               ret_val = e1000_read_flash_byte_ich8lan(hw, act_offset,
+                                                       &sig_byte);
+               if (ret_val)
+                       return ret_val;
+               if ((sig_byte & E1000_ICH_NVM_VALID_SIG_MASK) ==
+                   E1000_ICH_NVM_SIG_VALUE) {
                        *bank = 0;
-               } else {
-                       /*
-                        * find if segment 1 is valid by verifying
-                        * bit 15:14 = 10b in word 0x13
-                        */
-                       e1000_read_flash_byte_ich8lan(hw,
-                                                     act_offset + bank1_offset,
-                                                     &bank_high_byte);
+                       return 0;
+               }
 
-                       /* bank1 has a valid signature equivalent to SEC1V */
-                       if ((bank_high_byte & 0xC0) == 0x80) {
-                               *bank = 1;
-                       } else {
-                               hw_dbg(hw, "ERROR: EEPROM not present\n");
-                               return -E1000_ERR_NVM;
-                       }
+               /* Check bank 1 */
+               ret_val = e1000_read_flash_byte_ich8lan(hw, act_offset +
+                                                       bank1_offset,
+                                                       &sig_byte);
+               if (ret_val)
+                       return ret_val;
+               if ((sig_byte & E1000_ICH_NVM_VALID_SIG_MASK) ==
+                   E1000_ICH_NVM_SIG_VALUE) {
+                       *bank = 1;
+                       return 0;
                }
+
+               hw_dbg(hw, "ERROR: No valid NVM bank present\n");
+               return -E1000_ERR_NVM;
        }
 
        return 0;
@@ -1027,11 +1048,11 @@ static s32 e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words,
 
        ret_val = e1000_acquire_swflag_ich8lan(hw);
        if (ret_val)
-               return ret_val;
+               goto out;
 
        ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank);
        if (ret_val)
-               return ret_val;
+               goto release;
 
        act_offset = (bank) ? nvm->flash_bank_size : 0;
        act_offset += offset;
@@ -1050,8 +1071,13 @@ static s32 e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words,
                }
        }
 
+release:
        e1000_release_swflag_ich8lan(hw);
 
+out:
+       if (ret_val)
+               hw_dbg(hw, "NVM read error: %d\n", ret_val);
+
        return ret_val;
 }
 
@@ -1340,14 +1366,14 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
 
        ret_val = e1000e_update_nvm_checksum_generic(hw);
        if (ret_val)
-               return ret_val;
+               goto out;
 
        if (nvm->type != e1000_nvm_flash_sw)
-               return ret_val;
+               goto out;
 
        ret_val = e1000_acquire_swflag_ich8lan(hw);
        if (ret_val)
-               return ret_val;
+               goto out;
 
        /*
         * We're writing to the opposite bank so if we're on bank 1,
@@ -1355,17 +1381,27 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
         * is going to be written
         */
        ret_val =  e1000_valid_nvm_bank_detect_ich8lan(hw, &bank);
-       if (ret_val)
-               return ret_val;
+       if (ret_val) {
+               e1000_release_swflag_ich8lan(hw);
+               goto out;
+       }
 
        if (bank == 0) {
                new_bank_offset = nvm->flash_bank_size;
                old_bank_offset = 0;
-               e1000_erase_flash_bank_ich8lan(hw, 1);
+               ret_val = e1000_erase_flash_bank_ich8lan(hw, 1);
+               if (ret_val) {
+                       e1000_release_swflag_ich8lan(hw);
+                       goto out;
+               }
        } else {
                old_bank_offset = nvm->flash_bank_size;
                new_bank_offset = 0;
-               e1000_erase_flash_bank_ich8lan(hw, 0);
+               ret_val = e1000_erase_flash_bank_ich8lan(hw, 0);
+               if (ret_val) {
+                       e1000_release_swflag_ich8lan(hw);
+                       goto out;
+               }
        }
 
        for (i = 0; i < E1000_ICH8_SHADOW_RAM_WORDS; i++) {
@@ -1377,9 +1413,11 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
                if (dev_spec->shadow_ram[i].modified) {
                        data = dev_spec->shadow_ram[i].value;
                } else {
-                       e1000_read_flash_word_ich8lan(hw,
-                                                     i + old_bank_offset,
-                                                     &data);
+                       ret_val = e1000_read_flash_word_ich8lan(hw, i +
+                                                               old_bank_offset,
+                                                               &data);
+                       if (ret_val)
+                               break;
                }
 
                /*
@@ -1420,7 +1458,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
                /* Possibly read-only, see e1000e_write_protect_nvm_ich8lan() */
                hw_dbg(hw, "Flash commit failed.\n");
                e1000_release_swflag_ich8lan(hw);
-               return ret_val;
+               goto out;
        }
 
        /*
@@ -1430,14 +1468,18 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
         * and we need to change bit 14 to 0b
         */
        act_offset = new_bank_offset + E1000_ICH_NVM_SIG_WORD;
-       e1000_read_flash_word_ich8lan(hw, act_offset, &data);
+       ret_val = e1000_read_flash_word_ich8lan(hw, act_offset, &data);
+       if (ret_val) {
+               e1000_release_swflag_ich8lan(hw);
+               goto out;
+       }
        data &= 0xBFFF;
        ret_val = e1000_retry_write_flash_byte_ich8lan(hw,
                                                       act_offset * 2 + 1,
                                                       (u8)(data >> 8));
        if (ret_val) {
                e1000_release_swflag_ich8lan(hw);
-               return ret_val;
+               goto out;
        }
 
        /*
@@ -1450,7 +1492,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
        ret_val = e1000_retry_write_flash_byte_ich8lan(hw, act_offset, 0);
        if (ret_val) {
                e1000_release_swflag_ich8lan(hw);
-               return ret_val;
+               goto out;
        }
 
        /* Great!  Everything worked, we can now clear the cached entries. */
@@ -1468,6 +1510,10 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
        e1000e_reload_nvm(hw);
        msleep(10);
 
+out:
+       if (ret_val)
+               hw_dbg(hw, "NVM update error: %d\n", ret_val);
+
        return ret_val;
 }
 
@@ -1894,7 +1940,7 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
        }
        ret_val = e1000_acquire_swflag_ich8lan(hw);
        /* Whether or not the swflag was acquired, we need to reset the part */
-       hw_dbg(hw, "Issuing a global reset to ich8lan");
+       hw_dbg(hw, "Issuing a global reset to ich8lan\n");
        ew32(CTRL, (ctrl | E1000_CTRL_RST));
        msleep(20);
 
@@ -2074,12 +2120,17 @@ static s32 e1000_setup_link_ich8lan(struct e1000_hw *hw)
         * the default flow control setting, so we explicitly
         * set it to full.
         */
-       if (hw->fc.type == e1000_fc_default)
-               hw->fc.type = e1000_fc_full;
+       if (hw->fc.requested_mode == e1000_fc_default)
+               hw->fc.requested_mode = e1000_fc_full;
 
-       hw->fc.original_type = hw->fc.type;
+       /*
+        * Save off the requested flow control mode for use later.  Depending
+        * on the link partner's capabilities, we may or may not use this mode.
+        */
+       hw->fc.current_mode = hw->fc.requested_mode;
 
-       hw_dbg(hw, "After fix-ups FlowControl is now = %x\n", hw->fc.type);
+       hw_dbg(hw, "After fix-ups FlowControl is now = %x\n",
+               hw->fc.current_mode);
 
        /* Continue to configure the copper link. */
        ret_val = e1000_setup_copper_link_ich8lan(hw);