summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorMiles Xu, Sun Microsystems <Min.Xu@Sun.COM>2009-11-10 11:52:20 +0800
committerMiles Xu, Sun Microsystems <Min.Xu@Sun.COM>2009-11-10 11:52:20 +0800
commitbd9f6899328e19cbb74e3ad02f5c32002285887e (patch)
treeb7fc6650f149e4e8d904b8a1c74a632066147e86 /usr/src
parent98c507c4288789fc67365c4cb51f80eb641e7182 (diff)
downloadillumos-gate-bd9f6899328e19cbb74e3ad02f5c32002285887e.tar.gz
6893285 e1000g 'pciex8086,105e' with PHY type igp I/O devices have been retired
6895459 e1000g share code update v3-1-10-1
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/uts/common/io/e1000g/README5
-rw-r--r--usr/src/uts/common/io/e1000g/e1000_80003es2lan.c2
-rw-r--r--usr/src/uts/common/io/e1000g/e1000_80003es2lan.h2
-rw-r--r--usr/src/uts/common/io/e1000g/e1000_82540.c2
-rw-r--r--usr/src/uts/common/io/e1000g/e1000_82541.c2
-rw-r--r--usr/src/uts/common/io/e1000g/e1000_82541.h2
-rw-r--r--usr/src/uts/common/io/e1000g/e1000_82542.c2
-rw-r--r--usr/src/uts/common/io/e1000g/e1000_82543.c2
-rw-r--r--usr/src/uts/common/io/e1000g/e1000_82543.h2
-rw-r--r--usr/src/uts/common/io/e1000g/e1000_82571.c3
-rw-r--r--usr/src/uts/common/io/e1000g/e1000_82571.h2
-rw-r--r--usr/src/uts/common/io/e1000g/e1000_api.c2
-rw-r--r--usr/src/uts/common/io/e1000g/e1000_api.h2
-rw-r--r--usr/src/uts/common/io/e1000g/e1000_defines.h3
-rw-r--r--usr/src/uts/common/io/e1000g/e1000_hw.h6
-rw-r--r--usr/src/uts/common/io/e1000g/e1000_ich8lan.c572
-rw-r--r--usr/src/uts/common/io/e1000g/e1000_ich8lan.h26
-rw-r--r--usr/src/uts/common/io/e1000g/e1000_mac.c4
-rw-r--r--usr/src/uts/common/io/e1000g/e1000_mac.h2
-rw-r--r--usr/src/uts/common/io/e1000g/e1000_manage.c2
-rw-r--r--usr/src/uts/common/io/e1000g/e1000_manage.h2
-rw-r--r--usr/src/uts/common/io/e1000g/e1000_nvm.c2
-rw-r--r--usr/src/uts/common/io/e1000g/e1000_nvm.h2
-rw-r--r--usr/src/uts/common/io/e1000g/e1000_phy.c510
-rw-r--r--usr/src/uts/common/io/e1000g/e1000_phy.h18
-rw-r--r--usr/src/uts/common/io/e1000g/e1000_regs.h2
-rw-r--r--usr/src/uts/common/io/e1000g/e1000g_main.c2
27 files changed, 873 insertions, 310 deletions
diff --git a/usr/src/uts/common/io/e1000g/README b/usr/src/uts/common/io/e1000g/README
index bb3f892d29..47b86d6050 100644
--- a/usr/src/uts/common/io/e1000g/README
+++ b/usr/src/uts/common/io/e1000g/README
@@ -714,3 +714,8 @@ Notes on packaging:
6881588 e1000g functions should return when e1000g_check_dma_handle() fails
6888320 e1000g emits scary mutex message on the console
+5.3.17
+======
+ This version has the following fixes:
+ 6893285 e1000g 'pciex8086,105e' with PHY type igp I/O devices have been retired
+ 6895459 e1000g share code update v3-1-10-1
diff --git a/usr/src/uts/common/io/e1000g/e1000_80003es2lan.c b/usr/src/uts/common/io/e1000g/e1000_80003es2lan.c
index 48d8e64e98..4481425959 100644
--- a/usr/src/uts/common/io/e1000g/e1000_80003es2lan.c
+++ b/usr/src/uts/common/io/e1000g/e1000_80003es2lan.c
@@ -24,7 +24,7 @@
*/
/*
- * IntelVersion: 1.86 v3-1-3_2009-8-20
+ * IntelVersion: 1.86 v3-1-10-1_2009-9-18_Release14-6
*/
/*
* 80003ES2LAN Gigabit Ethernet Controller (Copper)
diff --git a/usr/src/uts/common/io/e1000g/e1000_80003es2lan.h b/usr/src/uts/common/io/e1000g/e1000_80003es2lan.h
index f020b59fd7..2b2fbac500 100644
--- a/usr/src/uts/common/io/e1000g/e1000_80003es2lan.h
+++ b/usr/src/uts/common/io/e1000g/e1000_80003es2lan.h
@@ -24,7 +24,7 @@
*/
/*
- * IntelVersion: 1.10 v3-1-3_2009-8-20
+ * IntelVersion: 1.10 v3-1-10-1_2009-9-18_Release14-6
*/
#ifndef _E1000_80003ES2LAN_H_
#define _E1000_80003ES2LAN_H_
diff --git a/usr/src/uts/common/io/e1000g/e1000_82540.c b/usr/src/uts/common/io/e1000g/e1000_82540.c
index 6ffa02b27e..3d9781e259 100644
--- a/usr/src/uts/common/io/e1000g/e1000_82540.c
+++ b/usr/src/uts/common/io/e1000g/e1000_82540.c
@@ -24,7 +24,7 @@
*/
/*
- * IntelVersion: 1.57 v3-1-3_2009-8-20
+ * IntelVersion: 1.57 v3-1-10-1_2009-9-18_Release14-6
*/
/*
diff --git a/usr/src/uts/common/io/e1000g/e1000_82541.c b/usr/src/uts/common/io/e1000g/e1000_82541.c
index 636d12da95..e57e2d3acd 100644
--- a/usr/src/uts/common/io/e1000g/e1000_82541.c
+++ b/usr/src/uts/common/io/e1000g/e1000_82541.c
@@ -24,7 +24,7 @@
*/
/*
- * IntelVersion: 1.68 v3-1-3_2009-8-20
+ * IntelVersion: 1.68 v3-1-10-1_2009-9-18_Release14-6
*/
/*
diff --git a/usr/src/uts/common/io/e1000g/e1000_82541.h b/usr/src/uts/common/io/e1000g/e1000_82541.h
index 7b304cc8c5..9dba90a1df 100644
--- a/usr/src/uts/common/io/e1000g/e1000_82541.h
+++ b/usr/src/uts/common/io/e1000g/e1000_82541.h
@@ -24,7 +24,7 @@
*/
/*
- * IntelVersion: 1.9 v3-1-3_2009-8-20
+ * IntelVersion: 1.9 v3-1-10-1_2009-9-18_Release14-6
*/
#ifndef _E1000_82541_H_
#define _E1000_82541_H_
diff --git a/usr/src/uts/common/io/e1000g/e1000_82542.c b/usr/src/uts/common/io/e1000g/e1000_82542.c
index 60aeae7084..d4e8636f16 100644
--- a/usr/src/uts/common/io/e1000g/e1000_82542.c
+++ b/usr/src/uts/common/io/e1000g/e1000_82542.c
@@ -24,7 +24,7 @@
*/
/*
- * IntelVersion: 1.53 v3-1-3_2009-8-20
+ * IntelVersion: 1.53 v3-1-10-1_2009-9-18_Release14-6
*/
/*
diff --git a/usr/src/uts/common/io/e1000g/e1000_82543.c b/usr/src/uts/common/io/e1000g/e1000_82543.c
index b11e27372b..6979501cbc 100644
--- a/usr/src/uts/common/io/e1000g/e1000_82543.c
+++ b/usr/src/uts/common/io/e1000g/e1000_82543.c
@@ -24,7 +24,7 @@
*/
/*
- * IntelVersion: 1.68 v3-1-3_2009-8-20
+ * IntelVersion: 1.68 v3-1-10-1_2009-9-18_Release14-6
*/
/*
diff --git a/usr/src/uts/common/io/e1000g/e1000_82543.h b/usr/src/uts/common/io/e1000g/e1000_82543.h
index 11adce4366..149f306b00 100644
--- a/usr/src/uts/common/io/e1000g/e1000_82543.h
+++ b/usr/src/uts/common/io/e1000g/e1000_82543.h
@@ -24,7 +24,7 @@
*/
/*
- * IntelVersion: 1.8 v3-1-3_2009-8-20
+ * IntelVersion: 1.8 v3-1-10-1_2009-9-18_Release14-6
*/
#ifndef _E1000_82543_H_
#define _E1000_82543_H_
diff --git a/usr/src/uts/common/io/e1000g/e1000_82571.c b/usr/src/uts/common/io/e1000g/e1000_82571.c
index be20186c07..b13be36f38 100644
--- a/usr/src/uts/common/io/e1000g/e1000_82571.c
+++ b/usr/src/uts/common/io/e1000g/e1000_82571.c
@@ -24,7 +24,7 @@
*/
/*
- * IntelVersion: 1.113 v3-1-3_2009-8-20
+ * IntelVersion: 1.113 v3-1-10-1_2009-9-18_Release14-6
*/
/*
@@ -845,7 +845,6 @@ e1000_get_cfg_done_82571(struct e1000_hw *hw)
}
if (!timeout) {
DEBUGOUT("MNG configuration cycle has not completed.\n");
- ret_val = -E1000_ERR_RESET;
goto out;
}
diff --git a/usr/src/uts/common/io/e1000g/e1000_82571.h b/usr/src/uts/common/io/e1000g/e1000_82571.h
index f548a82d30..98279ddd49 100644
--- a/usr/src/uts/common/io/e1000g/e1000_82571.h
+++ b/usr/src/uts/common/io/e1000g/e1000_82571.h
@@ -24,7 +24,7 @@
*/
/*
- * IntelVersion: 1.16 v3-1-3_2009-8-20
+ * IntelVersion: 1.16 v3-1-10-1_2009-9-18_Release14-6
*/
#ifndef _E1000_82571_H_
#define _E1000_82571_H_
diff --git a/usr/src/uts/common/io/e1000g/e1000_api.c b/usr/src/uts/common/io/e1000g/e1000_api.c
index 5b1873a237..44cd74d164 100644
--- a/usr/src/uts/common/io/e1000g/e1000_api.c
+++ b/usr/src/uts/common/io/e1000g/e1000_api.c
@@ -24,7 +24,7 @@
*/
/*
- * IntelVersion: 1.124 v3-1-3_2009-8-20
+ * IntelVersion: 1.125 v3-1-10-1_2009-9-18_Release14-6
*/
#include "e1000_api.h"
diff --git a/usr/src/uts/common/io/e1000g/e1000_api.h b/usr/src/uts/common/io/e1000g/e1000_api.h
index 6a2cf0c89b..a2ba7bcab1 100644
--- a/usr/src/uts/common/io/e1000g/e1000_api.h
+++ b/usr/src/uts/common/io/e1000g/e1000_api.h
@@ -24,7 +24,7 @@
*/
/*
- * IntelVersion: 1.53 v3-1-3_2009-8-20
+ * IntelVersion: 1.53 v3-1-10-1_2009-9-18_Release14-6
*/
#ifndef _E1000_API_H_
#define _E1000_API_H_
diff --git a/usr/src/uts/common/io/e1000g/e1000_defines.h b/usr/src/uts/common/io/e1000g/e1000_defines.h
index 449ffc9473..5927c6a263 100644
--- a/usr/src/uts/common/io/e1000g/e1000_defines.h
+++ b/usr/src/uts/common/io/e1000g/e1000_defines.h
@@ -24,7 +24,7 @@
*/
/*
- * IntelVersion: 1.116 v3-1-3_2009-8-20
+ * IntelVersion: 1.118 v3-1-10-1_2009-9-18_Release14-6
*/
#ifndef _E1000_DEFINES_H_
#define _E1000_DEFINES_H_
@@ -691,6 +691,7 @@
/* Extended Configuration Control and Size */
#define E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP 0x00000020
#define E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE 0x00000001
+#define E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE 0x00000008
#define E1000_EXTCNF_CTRL_SWFLAG 0x00000020
#define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK 0x00FF0000
#define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT 16
diff --git a/usr/src/uts/common/io/e1000g/e1000_hw.h b/usr/src/uts/common/io/e1000g/e1000_hw.h
index 9a4dbdfa64..723ca8ee27 100644
--- a/usr/src/uts/common/io/e1000g/e1000_hw.h
+++ b/usr/src/uts/common/io/e1000g/e1000_hw.h
@@ -24,7 +24,7 @@
*/
/*
- * IntelVersion: 1.432 v3-1-3_2009-8-20
+ * IntelVersion: 1.439 v3-1-10-1_2009-9-18_Release14-6
*/
#ifndef _E1000_HW_H_
#define _E1000_HW_H_
@@ -603,11 +603,13 @@ struct e1000_phy_operations {
s32 (*get_cable_length)(struct e1000_hw *);
s32 (*get_info)(struct e1000_hw *);
s32 (*read_reg)(struct e1000_hw *, u32, u16 *);
+ s32 (*read_reg_locked)(struct e1000_hw *, u32, u16 *);
void (*release)(struct e1000_hw *);
s32 (*reset)(struct e1000_hw *);
s32 (*set_d0_lplu_state)(struct e1000_hw *, bool);
s32 (*set_d3_lplu_state)(struct e1000_hw *, bool);
s32 (*write_reg)(struct e1000_hw *, u32, u16);
+ s32 (*write_reg_locked)(struct e1000_hw *, u32, u16);
void (*power_up)(struct e1000_hw *);
void (*power_down)(struct e1000_hw *);
};
@@ -774,6 +776,8 @@ struct e1000_dev_spec_ich8lan {
struct e1000_shadow_ram shadow_ram[E1000_SHADOW_RAM_WORDS];
E1000_MUTEX nvm_mutex;
E1000_MUTEX swflag_mutex;
+ bool nvm_k1_enabled;
+ bool nvm_lcd_config_enabled;
};
struct e1000_hw {
diff --git a/usr/src/uts/common/io/e1000g/e1000_ich8lan.c b/usr/src/uts/common/io/e1000g/e1000_ich8lan.c
index cd62381fdf..13494bcbd4 100644
--- a/usr/src/uts/common/io/e1000g/e1000_ich8lan.c
+++ b/usr/src/uts/common/io/e1000g/e1000_ich8lan.c
@@ -24,7 +24,7 @@
*/
/*
- * IntelVersion: 1.180 v3-1-3_2009-8-20
+ * IntelVersion: 1.186.2.1 v3-1-10-1_2009-9-18_Release14-6
*/
/*
@@ -69,6 +69,7 @@ static bool e1000_check_mng_mode_ich8lan(struct e1000_hw *hw);
static s32 e1000_check_reset_block_ich8lan(struct e1000_hw *hw);
static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw);
static s32 e1000_get_phy_info_ich8lan(struct e1000_hw *hw);
+static s32 e1000_set_lplu_state_pchlan(struct e1000_hw *hw, bool active);
static s32 e1000_set_d0_lplu_state_ich8lan(struct e1000_hw *hw,
bool active);
static s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw,
@@ -92,10 +93,11 @@ static s32 e1000_get_link_up_info_ich8lan(struct e1000_hw *hw,
static s32 e1000_cleanup_led_ich8lan(struct e1000_hw *hw);
static s32 e1000_led_on_ich8lan(struct e1000_hw *hw);
static s32 e1000_led_off_ich8lan(struct e1000_hw *hw);
-static s32 e1000_setup_led_pchlan(struct e1000_hw *hw);
-static s32 e1000_cleanup_led_pchlan(struct e1000_hw *hw);
-static s32 e1000_led_on_pchlan(struct e1000_hw *hw);
-static s32 e1000_led_off_pchlan(struct e1000_hw *hw);
+static s32 e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link);
+static s32 e1000_setup_led_pchlan(struct e1000_hw *hw);
+static s32 e1000_cleanup_led_pchlan(struct e1000_hw *hw);
+static s32 e1000_led_on_pchlan(struct e1000_hw *hw);
+static s32 e1000_led_off_pchlan(struct e1000_hw *hw);
static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw);
static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank);
static s32 e1000_flash_cycle_ich8lan(struct e1000_hw *hw, u32 timeout);
@@ -118,6 +120,8 @@ static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
static s32 e1000_get_cfg_done_ich8lan(struct e1000_hw *hw);
static void e1000_power_down_phy_copper_ich8lan(struct e1000_hw *hw);
static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw);
+static void e1000_lan_init_done_ich8lan(struct e1000_hw *hw);
+static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw);
/* ICH GbE Flash Hardware Sequencing Flash Status Register bit breakdown */
/* Offset 04h HSFSTS */
@@ -185,11 +189,13 @@ e1000_init_phy_params_pchlan(struct e1000_hw *hw)
phy->ops.get_cfg_done = e1000_get_cfg_done_ich8lan;
phy->ops.get_info = e1000_get_phy_info_ich8lan;
phy->ops.read_reg = e1000_read_phy_reg_hv;
+ phy->ops.read_reg_locked = e1000_read_phy_reg_hv_locked;
phy->ops.release = e1000_release_swflag_ich8lan;
phy->ops.reset = e1000_phy_hw_reset_ich8lan;
- phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_ich8lan;
- phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_ich8lan;
+ phy->ops.set_d0_lplu_state = e1000_set_lplu_state_pchlan;
+ phy->ops.set_d3_lplu_state = e1000_set_lplu_state_pchlan;
phy->ops.write_reg = e1000_write_phy_reg_hv;
+ phy->ops.write_reg_locked = e1000_write_phy_reg_hv_locked;
phy->ops.power_up = e1000_power_up_phy_copper;
phy->ops.power_down = e1000_power_down_phy_copper_ich8lan;
phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT;
@@ -273,6 +279,8 @@ e1000_init_phy_params_ich8lan(struct e1000_hw *hw)
case IGP03E1000_E_PHY_ID:
phy->type = e1000_phy_igp_3;
phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT;
+ phy->ops.read_reg_locked = e1000_read_phy_reg_igp_locked;
+ phy->ops.write_reg_locked = e1000_write_phy_reg_igp_locked;
break;
case IFE_E_PHY_ID:
case IFE_PLUS_E_PHY_ID:
@@ -491,14 +499,6 @@ e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
goto out;
}
- if (hw->mac.type == e1000_pchlan) {
- ret_val = e1000_write_kmrn_reg_generic(hw,
- E1000_KMRNCTRLSTA_K1_CONFIG,
- E1000_KMRNCTRLSTA_K1_ENABLE);
- if (ret_val)
- goto out;
- }
-
/*
* First we want to see if the MII Status Register reports
* link. If so, then we want to get the current speed/duplex
@@ -508,6 +508,12 @@ e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
if (ret_val)
goto out;
+ if (hw->mac.type == e1000_pchlan) {
+ ret_val = e1000_k1_gig_workaround_hv(hw, link);
+ if (ret_val)
+ goto out;
+ }
+
if (!link)
goto out; /* No link detected */
@@ -616,9 +622,8 @@ e1000_release_nvm_ich8lan(struct e1000_hw *hw)
* e1000_acquire_swflag_ich8lan - Acquire software control flag
* @hw: pointer to the HW structure
*
- * Acquires the software control flag for performing NVM and PHY
- * operations. This is a function pointer entry point only called by
- * read/write routines for the PHY and NVM parts.
+ * Acquires the software control flag for performing PHY and select
+ * MAC CSR accesses.
*/
static s32
e1000_acquire_swflag_ich8lan(struct e1000_hw *hw)
@@ -652,9 +657,9 @@ e1000_acquire_swflag_ich8lan(struct e1000_hw *hw)
E1000_WRITE_REG(hw, E1000_EXTCNF_CTRL, extcnf_ctrl);
while (timeout) {
- extcnf_ctrl = E1000_READ_REG(hw, E1000_EXTCNF_CTRL);
- if (extcnf_ctrl & E1000_EXTCNF_CTRL_SWFLAG)
- break;
+ extcnf_ctrl = E1000_READ_REG(hw, E1000_EXTCNF_CTRL);
+ if (extcnf_ctrl & E1000_EXTCNF_CTRL_SWFLAG)
+ break;
msec_delay_irq(1);
timeout--;
@@ -679,9 +684,8 @@ out:
* e1000_release_swflag_ich8lan - Release software control flag
* @hw: pointer to the HW structure
*
- * Releases the software control flag for performing NVM and PHY operations.
- * This is a function pointer entry point only called by read/write
- * routines for the PHY and NVM parts.
+ * Releases the software control flag for performing PHY and select
+ * MAC CSR accesses.
*/
static void
e1000_release_swflag_ich8lan(struct e1000_hw *hw)
@@ -740,6 +744,343 @@ e1000_check_reset_block_ich8lan(struct e1000_hw *hw)
}
/*
+ * e1000_sw_lcd_config_ich8lan - SW-based LCD Configuration
+ * @hw: pointer to the HW structure
+ *
+ * SW should configure the LCD from the NVM extended configuration region
+ * as a workaround for certain parts.
+ */
+static s32
+e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw)
+{
+ struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
+ struct e1000_phy_info *phy = &hw->phy;
+ u32 i, data, cnf_size, cnf_base_addr, sw_cfg_mask;
+ s32 ret_val;
+ u16 word_addr, reg_data, reg_addr, phy_page = 0;
+
+ ret_val = hw->phy.ops.acquire(hw);
+ if (ret_val)
+ return (ret_val);
+
+ /*
+ * Initialize the PHY from the NVM on ICH platforms. This
+ * is needed due to an issue where the NVM configuration is
+ * not properly autoloaded after power transitions.
+ * Therefore, after each PHY reset, we will load the
+ * configuration data out of the NVM manually.
+ */
+ if ((hw->mac.type == e1000_ich8lan && phy->type == e1000_phy_igp_3) ||
+ (hw->mac.type == e1000_pchlan)) {
+ /* Check if SW needs to configure the PHY */
+ if ((hw->device_id == E1000_DEV_ID_ICH8_IGP_M_AMT) ||
+ (hw->device_id == E1000_DEV_ID_ICH8_IGP_M) ||
+ (hw->mac.type == e1000_pchlan))
+ sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG_ICH8M;
+ else
+ sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG;
+
+ data = E1000_READ_REG(hw, E1000_FEXTNVM);
+ if (!(data & sw_cfg_mask))
+ goto out;
+
+ /* Wait for basic configuration completes before proceeding */
+ e1000_lan_init_done_ich8lan(hw);
+
+ /*
+ * Make sure HW does not configure LCD from PHY
+ * extended configuration before SW configuration
+ */
+ data = E1000_READ_REG(hw, E1000_EXTCNF_CTRL);
+ if (data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE)
+ goto out;
+
+ cnf_size = E1000_READ_REG(hw, E1000_EXTCNF_SIZE);
+ cnf_size &= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK;
+ cnf_size >>= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT;
+ if (!cnf_size)
+ goto out;
+
+ cnf_base_addr = data & E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK;
+ cnf_base_addr >>= E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT;
+
+ if (!(data & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE) &&
+ hw->mac.type == e1000_pchlan) {
+ /*
+ * HW configures the SMBus address and LEDs when the
+ * OEM and LCD Write Enable bits are set in the NVM.
+ * When both NVM bits are cleared, SW will configure
+ * them instead.
+ */
+ data = E1000_READ_REG(hw, E1000_STRAP);
+ data &= E1000_STRAP_SMBUS_ADDRESS_MASK;
+ reg_data = data >> E1000_STRAP_SMBUS_ADDRESS_SHIFT;
+ reg_data |= HV_SMB_ADDR_PEC_EN | HV_SMB_ADDR_VALID;
+ ret_val = e1000_write_phy_reg_hv_locked(hw, HV_SMB_ADDR,
+ reg_data);
+ if (ret_val)
+ goto out;
+
+ data = E1000_READ_REG(hw, E1000_LEDCTL);
+ ret_val = e1000_write_phy_reg_hv_locked(hw,
+ HV_LED_CONFIG, (u16)data);
+ if (ret_val)
+ goto out;
+
+ dev_spec->nvm_lcd_config_enabled = true;
+ }
+ /* Configure LCD from extended configuration region. */
+
+ /* cnf_base_addr is in DWORD */
+ word_addr = (u16)(cnf_base_addr << 1);
+
+ for (i = 0; i < cnf_size; i++) {
+ ret_val = hw->nvm.ops.read(hw, (word_addr + i * 2), 1,
+ &reg_data);
+ if (ret_val)
+ goto out;
+
+ ret_val = hw->nvm.ops.read(hw, (word_addr + i * 2 + 1),
+ 1, &reg_addr);
+ if (ret_val)
+ goto out;
+
+ /* Save off the PHY page for future writes. */
+ if (reg_addr == IGP01E1000_PHY_PAGE_SELECT) {
+ phy_page = reg_data;
+ continue;
+ }
+ /*
+ * Bit 5 in the LCD config word contains the phy
+ * address for PCH
+ */
+ if (hw->mac.type == e1000_pchlan) {
+ phy->addr = 1;
+ if (reg_addr & LCD_CFG_PHY_ADDR_BIT) {
+ phy->addr = 2;
+ reg_addr &= PHY_REG_MASK;
+ }
+ }
+
+ reg_addr |= phy_page;
+
+ ret_val = phy->ops.write_reg_locked(hw, (u32)reg_addr,
+ reg_data);
+ if (ret_val)
+ goto out;
+ }
+
+ if (hw->mac.type == e1000_pchlan)
+ dev_spec->nvm_lcd_config_enabled = false;
+ }
+
+out:
+ hw->phy.ops.release(hw);
+ return (ret_val);
+}
+
+/*
+ * e1000_k1_gig_workaround_hv - K1 Si workaround
+ * @hw: pointer to the HW structure
+ * @link: link up bool flag
+ *
+ * If K1 is enabled for 1Gbps, the MAC might stall when transitioning
+ * from a lower speed. This workaround disables K1 whenever link is at 1Gig
+ * If link is down, the function will restore the default K1 setting located
+ * in the NVM.
+ */
+static s32
+e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link)
+{
+ s32 ret_val = E1000_SUCCESS;
+ u16 status_reg = 0;
+ bool k1_enable = hw->dev_spec.ich8lan.nvm_k1_enabled;
+
+ DEBUGFUNC("e1000_k1_gig_workaround_hv");
+
+ if (hw->mac.type != e1000_pchlan)
+ goto out;
+
+ /* Wrap the whole flow with the sw flag */
+ ret_val = hw->phy.ops.acquire(hw);
+ if (ret_val)
+ goto out;
+
+ /* Disable K1 when link is 1Gbps, otherwise use the NVM setting */
+ if (link) {
+ if (hw->phy.type == e1000_phy_82578) {
+ ret_val = hw->phy.ops.read_reg_locked(hw, BM_CS_STATUS,
+ &status_reg);
+ if (ret_val)
+ goto release;
+
+ status_reg &= BM_CS_STATUS_LINK_UP |
+ BM_CS_STATUS_RESOLVED |
+ BM_CS_STATUS_SPEED_MASK;
+
+ if (status_reg == (BM_CS_STATUS_LINK_UP |
+ BM_CS_STATUS_RESOLVED |
+ BM_CS_STATUS_SPEED_1000))
+ k1_enable = false;
+ }
+
+ if (hw->phy.type == e1000_phy_82577) {
+ ret_val = hw->phy.ops.read_reg_locked(hw, HV_M_STATUS,
+ &status_reg);
+ if (ret_val)
+ goto release;
+
+ status_reg &= HV_M_STATUS_LINK_UP |
+ HV_M_STATUS_AUTONEG_COMPLETE |
+ HV_M_STATUS_SPEED_MASK;
+
+ if (status_reg == (HV_M_STATUS_LINK_UP |
+ HV_M_STATUS_AUTONEG_COMPLETE |
+ HV_M_STATUS_SPEED_1000))
+ k1_enable = false;
+ }
+
+ /* Link stall fix for link up */
+ ret_val = hw->phy.ops.write_reg_locked(hw, PHY_REG(770, 19),
+ 0x0100);
+ if (ret_val)
+ goto release;
+
+ } else {
+ /* Link stall fix for link down */
+ ret_val = hw->phy.ops.write_reg_locked(hw, PHY_REG(770, 19),
+ 0x4100);
+ if (ret_val)
+ goto release;
+ }
+
+ ret_val = e1000_configure_k1_ich8lan(hw, k1_enable);
+
+release:
+ hw->phy.ops.release(hw);
+out:
+ return (ret_val);
+}
+
+/*
+ * e1000_configure_k1_ich8lan - Configure K1 power state
+ * @hw: pointer to the HW structure
+ * @enable: K1 state to configure
+ *
+ * Configure the K1 power state based on the provided parameter.
+ * Assumes semaphore already acquired.
+ *
+ * Success returns 0, Failure returns -E1000_ERR_PHY (-2)
+ */
+s32
+e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable)
+{
+ s32 ret_val = E1000_SUCCESS;
+ u32 ctrl_reg = 0;
+ u32 ctrl_ext = 0;
+ u32 reg = 0;
+ u16 kmrn_reg = 0;
+
+ ret_val = e1000_read_kmrn_reg_locked(hw,
+ E1000_KMRNCTRLSTA_K1_CONFIG,
+ &kmrn_reg);
+ if (ret_val)
+ goto out;
+
+ if (k1_enable)
+ kmrn_reg |= E1000_KMRNCTRLSTA_K1_ENABLE;
+ else
+ kmrn_reg &= ~E1000_KMRNCTRLSTA_K1_ENABLE;
+
+ ret_val = e1000_write_kmrn_reg_locked(hw,
+ E1000_KMRNCTRLSTA_K1_CONFIG,
+ kmrn_reg);
+ if (ret_val)
+ goto out;
+
+ usec_delay(20);
+ ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
+ ctrl_reg = E1000_READ_REG(hw, E1000_CTRL);
+
+ reg = ctrl_reg & ~(E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100);
+ reg |= E1000_CTRL_FRCSPD;
+ E1000_WRITE_REG(hw, E1000_CTRL, reg);
+
+ E1000_WRITE_REG(hw,
+ E1000_CTRL_EXT,
+ ctrl_ext | E1000_CTRL_EXT_SPD_BYPS);
+ usec_delay(20);
+ E1000_WRITE_REG(hw, E1000_CTRL, ctrl_reg);
+ E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
+ usec_delay(20);
+
+out:
+ return (ret_val);
+}
+
+/*
+ * e1000_oem_bits_config_ich8lan - SW-based LCD Configuration
+ * @hw: pointer to the HW structure
+ * @d0_state: boolean if entering d0 or d3 device state
+ *
+ * SW will configure Gbe Disable and LPLU based on the NVM. The four bits are
+ * collectively called OEM bits. The OEM Write Enable bit and SW Config bit
+ * in NVM determines whether HW should configure LPLU and Gbe Disable.
+ */
+s32
+e1000_oem_bits_config_ich8lan(struct e1000_hw *hw, bool d0_state)
+{
+ s32 ret_val = 0;
+ u32 mac_reg;
+ u16 oem_reg;
+
+ if (hw->mac.type != e1000_pchlan)
+ return (ret_val);
+
+ ret_val = hw->phy.ops.acquire(hw);
+ if (ret_val)
+ return (ret_val);
+
+ mac_reg = E1000_READ_REG(hw, E1000_EXTCNF_CTRL);
+ if (mac_reg & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE)
+ goto out;
+
+ mac_reg = E1000_READ_REG(hw, E1000_FEXTNVM);
+ if (!(mac_reg & E1000_FEXTNVM_SW_CONFIG_ICH8M))
+ goto out;
+
+ mac_reg = E1000_READ_REG(hw, E1000_PHY_CTRL);
+
+ ret_val = hw->phy.ops.read_reg_locked(hw, HV_OEM_BITS, &oem_reg);
+ if (ret_val)
+ goto out;
+
+ oem_reg &= ~(HV_OEM_BITS_GBE_DIS | HV_OEM_BITS_LPLU);
+
+ if (d0_state) {
+ if (mac_reg & E1000_PHY_CTRL_GBE_DISABLE)
+ oem_reg |= HV_OEM_BITS_GBE_DIS;
+
+ if (mac_reg & E1000_PHY_CTRL_D0A_LPLU)
+ oem_reg |= HV_OEM_BITS_LPLU;
+ } else {
+ if (mac_reg & E1000_PHY_CTRL_NOND0A_GBE_DISABLE)
+ oem_reg |= HV_OEM_BITS_GBE_DIS;
+
+ if (mac_reg & E1000_PHY_CTRL_NOND0A_LPLU)
+ oem_reg |= HV_OEM_BITS_LPLU;
+ }
+ /* Restart auto-neg to activate the bits */
+ oem_reg |= HV_OEM_BITS_RESTART_AN;
+ ret_val = hw->phy.ops.write_reg_locked(hw, HV_OEM_BITS, oem_reg);
+
+out:
+ hw->phy.ops.release(hw);
+
+ return (ret_val);
+}
+
+/*
* e1000_hv_phy_workarounds_ich8lan - A series of Phy workarounds to be
* done after every PHY reset.
*/
@@ -749,7 +1090,7 @@ e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw)
s32 ret_val = E1000_SUCCESS;
if (hw->mac.type != e1000_pchlan)
- return (ret_val);
+ goto out;
if (((hw->phy.type == e1000_phy_82577) &&
((hw->phy.revision == 1) || (hw->phy.revision == 2))) ||
@@ -757,12 +1098,12 @@ e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw)
/* Disable generation of early preamble */
ret_val = hw->phy.ops.write_reg(hw, PHY_REG(769, 25), 0x4431);
if (ret_val)
- return (ret_val);
+ goto out;
/* Preamble tuning for SSC */
ret_val = hw->phy.ops.write_reg(hw, PHY_REG(770, 16), 0xA204);
if (ret_val)
- return (ret_val);
+ goto out;
}
if (hw->phy.type == e1000_phy_82578) {
@@ -780,12 +1121,21 @@ e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw)
/* Select page 0 */
ret_val = hw->phy.ops.acquire(hw);
if (ret_val)
- return (ret_val);
+ goto out;
hw->phy.addr = 1;
- e1000_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, 0);
+ ret_val = e1000_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, 0);
+ if (ret_val)
+ goto out;
hw->phy.ops.release(hw);
+ /*
+ * Configure the K1 Si workaround during phy reset assuming there is
+ * link so that it disables K1 if link is in 1Gbps.
+ */
+ ret_val = e1000_k1_gig_workaround_hv(hw, true);
+
+out:
return (ret_val);
}
@@ -862,10 +1212,8 @@ e1000_lan_init_done_ich8lan(struct e1000_hw *hw)
static s32
e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw)
{
- struct e1000_phy_info *phy = &hw->phy;
- u32 i, data, cnf_size, cnf_base_addr, sw_cfg_mask;
- s32 ret_val;
- u16 word_addr, reg_data, reg_addr, phy_page = 0;
+ s32 ret_val = E1000_SUCCESS;
+ u16 reg;
DEBUGFUNC("e1000_phy_hw_reset_ich8lan");
@@ -888,86 +1236,22 @@ e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw)
goto out;
}
- /*
- * Initialize the PHY from the NVM on ICH platforms. This is needed
- * due to an issue where the NVM configuration is not properly
- * autoloaded after power transitions. Therefore, after each PHY
- * reset, we will load the configuration data out of the NVM manually.
- */
- if (hw->mac.type == e1000_ich8lan && phy->type == e1000_phy_igp_3) {
- /* Check if SW needs configure the PHY */
- if ((hw->device_id == E1000_DEV_ID_ICH8_IGP_M_AMT) ||
- (hw->device_id == E1000_DEV_ID_ICH8_IGP_M))
- sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG_ICH8M;
- else
- sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG;
-
- data = E1000_READ_REG(hw, E1000_FEXTNVM);
- if (!(data & sw_cfg_mask))
- goto out;
-
- /* Wait for basic configuration completes before proceeding */
- e1000_lan_init_done_ich8lan(hw);
-
- /*
- * Make sure HW does not configure LCD from PHY extended
- * configuration before SW configuration
- */
- data = E1000_READ_REG(hw, E1000_EXTCNF_CTRL);
- if (data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE)
- goto out;
-
- cnf_size = E1000_READ_REG(hw, E1000_EXTCNF_SIZE);
- cnf_size &= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK;
- cnf_size >>= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT;
- if (!cnf_size)
- goto out;
-
- cnf_base_addr = data & E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK;
- cnf_base_addr >>= E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT;
-
- /*
- * Configure LCD from extended configuration region.
- */
-
- /* cnf_base_addr is in DWORD */
- word_addr = (u16)(cnf_base_addr << 1);
-
- for (i = 0; i < cnf_size; i++) {
- ret_val = hw->nvm.ops.read(hw,
- (word_addr + i * 2),
- 1,
- &reg_data);
- if (ret_val)
- goto out;
-
- ret_val = hw->nvm.ops.read(hw,
- (word_addr + i * 2 + 1),
- 1,
- &reg_addr);
- if (ret_val)
- goto out;
-
- /* Save off the PHY page for future writes. */
- if (reg_addr == IGP01E1000_PHY_PAGE_SELECT) {
- phy_page = reg_data;
- continue;
- }
+ /* Dummy read to clear the phy wakeup bit after lcd reset */
+ if (hw->mac.type == e1000_pchlan)
+ hw->phy.ops.read_reg(hw, BM_WUC, &reg);
- reg_addr |= phy_page;
+ /* Configure the LCD with the extended configuration region in NVM */
+ ret_val = e1000_sw_lcd_config_ich8lan(hw);
+ if (ret_val)
+ goto out;
- ret_val = phy->ops.write_reg(hw,
- (u32)reg_addr,
- reg_data);
- if (ret_val)
- goto out;
- }
- }
+ /* Configure the LCD with the OEM bits in NVM */
+ if (hw->mac.type == e1000_pchlan)
+ ret_val = e1000_oem_bits_config_ich8lan(hw, true);
out:
return (ret_val);
}
-
/*
* e1000_get_phy_info_ich8lan - Calls appropriate PHY type get_phy_info
* @hw: pointer to the HW structure
@@ -1059,6 +1343,41 @@ out:
}
/*
+ * e1000_set_lplu_state_pchlan - Set Low Power Link Up state
+ * @hw: pointer to the HW structure
+ * @active: true to enable LPLU, false to disable
+ *
+ * Sets the LPLU state according to the active flag. For PCH, if OEM write
+ * bit are disabled in the NVM, writing the LPLU bits in the MAC will not set
+ * the phy speed. This function will manually set the LPLU bit and restart
+ * auto-neg as hw would do. D3 and D0 LPLU will call the same function
+ * since it configures the same bit.
+ */
+static s32
+e1000_set_lplu_state_pchlan(struct e1000_hw *hw, bool active)
+{
+ s32 ret_val = E1000_SUCCESS;
+ u16 oem_reg;
+
+ DEBUGFUNC("e1000_set_lplu_state_pchlan");
+
+ ret_val = hw->phy.ops.read_reg(hw, HV_OEM_BITS, &oem_reg);
+ if (ret_val)
+ goto out;
+
+ if (active)
+ oem_reg |= HV_OEM_BITS_LPLU;
+ else
+ oem_reg &= ~HV_OEM_BITS_LPLU;
+
+ oem_reg |= HV_OEM_BITS_RESTART_AN;
+ ret_val = hw->phy.ops.write_reg(hw, HV_OEM_BITS, oem_reg);
+
+out:
+ return (ret_val);
+}
+
+/*
* e1000_set_d0_lplu_state_ich8lan - Set Low Power Linkup D0 state
* @hw: pointer to the HW structure
* @active: true to enable LPLU, false to disable
@@ -2288,6 +2607,8 @@ e1000_get_bus_info_ich8lan(struct e1000_hw *hw)
static s32
e1000_reset_hw_ich8lan(struct e1000_hw *hw)
{
+ struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
+ u16 reg;
u32 ctrl, kab;
s32 ret_val;
@@ -2323,6 +2644,18 @@ e1000_reset_hw_ich8lan(struct e1000_hw *hw)
E1000_WRITE_REG(hw, E1000_PBS, E1000_PBS_16K);
}
+ if (hw->mac.type == e1000_pchlan) {
+ /* Save the NVM K1 bit setting */
+ ret_val = e1000_read_nvm(hw, E1000_NVM_K1_CONFIG, 1, &reg);
+ if (ret_val)
+ return (ret_val);
+
+ if (reg & E1000_NVM_K1_ENABLE)
+ dev_spec->nvm_k1_enabled = true;
+ else
+ dev_spec->nvm_k1_enabled = false;
+ }
+
ctrl = E1000_READ_REG(hw, E1000_CTRL);
if (!hw->phy.ops.check_reset_block(hw) && !hw->phy.reset_disable) {
@@ -2367,6 +2700,20 @@ e1000_reset_hw_ich8lan(struct e1000_hw *hw)
}
}
+ /* Dummy read to clear the phy wakeup bit after lcd reset */
+ if (hw->mac.type == e1000_pchlan)
+ hw->phy.ops.read_reg(hw, BM_WUC, &reg);
+
+ ret_val = e1000_sw_lcd_config_ich8lan(hw);
+ if (ret_val)
+ goto out;
+
+ if (hw->mac.type == e1000_pchlan) {
+ ret_val = e1000_oem_bits_config_ich8lan(hw, true);
+ if (ret_val)
+ goto out;
+ }
+
/*
* For PCH, this write will make sure that any noise
* will be detected as a CRC error and be dropped rather than show up
@@ -2712,14 +3059,6 @@ e1000_get_link_up_info_ich8lan(struct e1000_hw *hw, u16 *speed, u16 *duplex)
if (ret_val)
goto out;
- if ((hw->mac.type == e1000_pchlan) && (*speed == SPEED_1000)) {
- ret_val = e1000_write_kmrn_reg_generic(hw,
- E1000_KMRNCTRLSTA_K1_CONFIG,
- E1000_KMRNCTRLSTA_K1_DISABLE);
- if (ret_val)
- goto out;
- }
-
if ((hw->mac.type == e1000_ich8lan) &&
(hw->phy.type == e1000_phy_igp_3) &&
(*speed == SPEED_1000)) {
@@ -2951,9 +3290,8 @@ e1000_disable_gig_wol_ich8lan(struct e1000_hw *hw)
E1000_PHY_CTRL_GBE_DISABLE;
E1000_WRITE_REG(hw, E1000_PHY_CTRL, phy_ctrl);
- /* Workaround SWFLAG unexpectedly set during S0->Sx */
if (hw->mac.type == e1000_pchlan)
- usec_delay(500);
+ e1000_phy_hw_reset_ich8lan(hw);
default:
break;
}
diff --git a/usr/src/uts/common/io/e1000g/e1000_ich8lan.h b/usr/src/uts/common/io/e1000g/e1000_ich8lan.h
index 3164e889df..48d0f95c12 100644
--- a/usr/src/uts/common/io/e1000g/e1000_ich8lan.h
+++ b/usr/src/uts/common/io/e1000g/e1000_ich8lan.h
@@ -24,7 +24,7 @@
*/
/*
- * IntelVersion: 1.37 v3-1-3_2009-8-20
+ * IntelVersion: 1.41 v3-1-10-1_2009-9-18_Release14-6
*/
#ifndef _E1000_ICH8LAN_H_
#define _E1000_ICH8LAN_H_
@@ -140,6 +140,28 @@ extern "C" {
/* PCH Flow Control Refresh Timer Value */
#define E1000_FCRTV_PCH 0x05F40
+
+#define E1000_NVM_K1_CONFIG 0x1B /* NVM K1 Config Word */
+#define E1000_NVM_K1_ENABLE 0x1 /* NVM Enable K1 bit */
+
+/* SMBus Address Phy Register */
+#define HV_SMB_ADDR PHY_REG(768, 26)
+#define HV_SMB_ADDR_PEC_EN 0x0200
+#define HV_SMB_ADDR_VALID 0x0080
+
+/* Strapping Option Register - RO */
+#define E1000_STRAP 0x0000C
+#define E1000_STRAP_SMBUS_ADDRESS_MASK 0x00FE0000
+#define E1000_STRAP_SMBUS_ADDRESS_SHIFT 17
+
+/* OEM Bits Phy Register */
+#define HV_OEM_BITS PHY_REG(768, 25)
+#define HV_OEM_BITS_LPLU 0x0004 /* Low Power Link Up */
+#define HV_OEM_BITS_GBE_DIS 0x0040 /* Gigabit Disable */
+#define HV_OEM_BITS_RESTART_AN 0x0400 /* Restart Auto-negotiation */
+/* Phy address bit from LCD Config word */
+#define LCD_CFG_PHY_ADDR_BIT 0x0020
+
/* SW Semaphore flag timeout in milliseconds */
#define SW_FLAG_TIMEOUT 400
@@ -172,6 +194,8 @@ void e1000_set_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw,
void e1000_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw);
void e1000_gig_downshift_workaround_ich8lan(struct e1000_hw *hw);
void e1000_disable_gig_wol_ich8lan(struct e1000_hw *hw);
+s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable);
+s32 e1000_oem_bits_config_ich8lan(struct e1000_hw *hw, bool d0_config);
#ifdef __cplusplus
}
diff --git a/usr/src/uts/common/io/e1000g/e1000_mac.c b/usr/src/uts/common/io/e1000g/e1000_mac.c
index 69cdc6f412..0a9f4dccdb 100644
--- a/usr/src/uts/common/io/e1000g/e1000_mac.c
+++ b/usr/src/uts/common/io/e1000g/e1000_mac.c
@@ -24,7 +24,7 @@
*/
/*
- * IntelVersion: 1.108 v3-1-3_2009-8-20
+ * IntelVersion: 1.108 v3-1-10-1_2009-9-18_Release14-6
*/
#include "e1000_api.h"
@@ -2184,7 +2184,7 @@ e1000_update_adaptive_generic(struct e1000_hw *hw)
* Verify that when not using auto-negotiation that MDI/MDIx is correctly
* set, which is forced to MDI mode only.
*/
-s32
+static s32
e1000_validate_mdi_setting_generic(struct e1000_hw *hw)
{
s32 ret_val = E1000_SUCCESS;
diff --git a/usr/src/uts/common/io/e1000g/e1000_mac.h b/usr/src/uts/common/io/e1000g/e1000_mac.h
index 210d83399e..022798b5a7 100644
--- a/usr/src/uts/common/io/e1000g/e1000_mac.h
+++ b/usr/src/uts/common/io/e1000g/e1000_mac.h
@@ -24,7 +24,7 @@
*/
/*
- * IntelVersion: 1.32 v3-1-3_2009-8-20
+ * IntelVersion: 1.32 v3-1-10-1_2009-9-18_Release14-6
*/
#ifndef _E1000_MAC_H_
#define _E1000_MAC_H_
diff --git a/usr/src/uts/common/io/e1000g/e1000_manage.c b/usr/src/uts/common/io/e1000g/e1000_manage.c
index 440eb4b10d..aa4c2d14b2 100644
--- a/usr/src/uts/common/io/e1000g/e1000_manage.c
+++ b/usr/src/uts/common/io/e1000g/e1000_manage.c
@@ -24,7 +24,7 @@
*/
/*
- * IntelVersion: 1.27 v3-1-3_2009-8-20
+ * IntelVersion: 1.27 v3-1-10-1_2009-9-18_Release14-6
*/
#include "e1000_api.h"
diff --git a/usr/src/uts/common/io/e1000g/e1000_manage.h b/usr/src/uts/common/io/e1000g/e1000_manage.h
index cb9f186356..0bae703485 100644
--- a/usr/src/uts/common/io/e1000g/e1000_manage.h
+++ b/usr/src/uts/common/io/e1000g/e1000_manage.h
@@ -24,7 +24,7 @@
*/
/*
- * IntelVersion: 1.18 v3-1-3_2009-8-20
+ * IntelVersion: 1.18 v3-1-10-1_2009-9-18_Release14-6
*/
#ifndef _E1000_MANAGE_H_
#define _E1000_MANAGE_H_
diff --git a/usr/src/uts/common/io/e1000g/e1000_nvm.c b/usr/src/uts/common/io/e1000g/e1000_nvm.c
index 1c00498071..10a904af34 100644
--- a/usr/src/uts/common/io/e1000g/e1000_nvm.c
+++ b/usr/src/uts/common/io/e1000g/e1000_nvm.c
@@ -24,7 +24,7 @@
*/
/*
- * IntelVersion: 1.49 v3-1-3_2009-8-20
+ * IntelVersion: 1.49 v3-1-10-1_2009-9-18_Release14-6
*/
#include "e1000_api.h"
diff --git a/usr/src/uts/common/io/e1000g/e1000_nvm.h b/usr/src/uts/common/io/e1000g/e1000_nvm.h
index 28a645a22a..9bb72407f5 100644
--- a/usr/src/uts/common/io/e1000g/e1000_nvm.h
+++ b/usr/src/uts/common/io/e1000g/e1000_nvm.h
@@ -24,7 +24,7 @@
*/
/*
- * IntelVersion: 1.18 v3-1-3_2009-8-20
+ * IntelVersion: 1.18 v3-1-10-1_2009-9-18_Release14-6
*/
#ifndef _E1000_NVM_H_
#define _E1000_NVM_H_
diff --git a/usr/src/uts/common/io/e1000g/e1000_phy.c b/usr/src/uts/common/io/e1000g/e1000_phy.c
index 87dfb78adc..b1e8166353 100644
--- a/usr/src/uts/common/io/e1000g/e1000_phy.c
+++ b/usr/src/uts/common/io/e1000g/e1000_phy.c
@@ -24,7 +24,7 @@
*/
/*
- * IntelVersion: 1.143 v3-1-3_2009-8-20
+ * IntelVersion: 1.151 v3-1-10-1_2009-9-18_Release14-6
*/
#include "e1000_api.h"
@@ -81,11 +81,13 @@ e1000_init_phy_ops_generic(struct e1000_hw *hw)
phy->ops.get_cable_length = e1000_null_ops_generic;
phy->ops.get_info = e1000_null_ops_generic;
phy->ops.read_reg = e1000_null_read_reg;
+ phy->ops.read_reg_locked = e1000_null_read_reg;
phy->ops.release = e1000_null_phy_generic;
phy->ops.reset = e1000_null_ops_generic;
phy->ops.set_d0_lplu_state = e1000_null_lplu_state;
phy->ops.set_d3_lplu_state = e1000_null_lplu_state;
phy->ops.write_reg = e1000_null_write_reg;
+ phy->ops.write_reg_locked = e1000_null_write_reg;
phy->ops.power_up = e1000_null_phy_generic;
phy->ops.power_down = e1000_null_phy_generic;
phy->ops.cfg_on_link_up = e1000_null_ops_generic;
@@ -197,21 +199,30 @@ e1000_get_phy_id(struct e1000_hw *hw)
goto out;
/*
- * If the PHY ID is still unknown, we may have an 82577 without
- * link. We will try again after setting Slow MDIC mode. No
- * harm in trying again in this case since the PHY ID is
- * unknown at this point anyway
+ * If the PHY ID is still unknown, we may have an 82577
+ * without link. We will try again after setting Slow MDIC
+ * mode. No harm in trying again in this case since the PHY
+ * ID is unknown at this point anyway.
*/
+ ret_val = phy->ops.acquire(hw);
+ if (ret_val)
+ goto out;
ret_val = e1000_set_mdio_slow_mode_hv(hw, true);
if (ret_val)
goto out;
+ phy->ops.release(hw);
retry_count++;
}
out:
/* Revert to MDIO fast mode, if applicable */
- if (retry_count)
+ if (retry_count) {
+ ret_val = phy->ops.acquire(hw);
+ if (ret_val)
+ return (ret_val);
ret_val = e1000_set_mdio_slow_mode_hv(hw, false);
+ phy->ops.release(hw);
+ }
return (ret_val);
}
@@ -425,111 +436,179 @@ out:
* @hw: pointer to the HW structure
* @offset: register offset to be read
* @data: pointer to the read data
+ * @locked: semaphore has already been acquired or not
*
* Acquires semaphore, if necessary, then reads the PHY register at offset
- * and storing the retrieved information in data. Release any acquired
+ * and stores the retrieved information in data. Release any acquired
* semaphores before exiting.
*/
-s32
-e1000_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data)
+static s32
+__e1000_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data,
+ bool locked)
{
s32 ret_val = E1000_SUCCESS;
- DEBUGFUNC("e1000_read_phy_reg_igp");
+ DEBUGFUNC("__e1000_read_phy_reg_igp");
- if (!(hw->phy.ops.acquire))
- goto out;
+ if (!locked) {
+ if (!(hw->phy.ops.acquire))
+ goto out;
- ret_val = hw->phy.ops.acquire(hw);
- if (ret_val)
- goto out;
+ ret_val = hw->phy.ops.acquire(hw);
+ if (ret_val)
+ goto out;
+ }
if (offset > MAX_PHY_MULTI_PAGE_REG) {
ret_val = e1000_write_phy_reg_mdic(hw,
- IGP01E1000_PHY_PAGE_SELECT,
- (u16)offset);
- if (ret_val) {
- hw->phy.ops.release(hw);
- goto out;
- }
+ IGP01E1000_PHY_PAGE_SELECT, (u16)offset);
+ if (ret_val)
+ goto release;
}
- ret_val = e1000_read_phy_reg_mdic(hw,
- MAX_PHY_REG_ADDRESS & offset,
- data);
- hw->phy.ops.release(hw);
+ ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
+ data);
+release:
+ if (!locked)
+ hw->phy.ops.release(hw);
out:
return (ret_val);
}
/*
+ * e1000_read_phy_reg_igp - Read igp PHY register
+ * @hw: pointer to the HW structure
+ * @offset: register offset to be read
+ * @data: pointer to the read data
+ *
+ * Acquires semaphore then reads the PHY register at offset and stores the
+ * retrieved information in data.
+ * Release the acquired semaphore before exiting.
+ */
+s32
+e1000_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data)
+{
+ return (__e1000_read_phy_reg_igp(hw, offset, data, false));
+}
+
+/*
+ * e1000_read_phy_reg_igp_locked - Read igp PHY register
+ * @hw: pointer to the HW structure
+ * @offset: register offset to be read
+ * @data: pointer to the read data
+ *
+ * Reads the PHY register at offset and stores the retrieved information
+ * in data. Assumes semaphore already acquired.
+ */
+s32
+e1000_read_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 *data)
+{
+ return (__e1000_read_phy_reg_igp(hw, offset, data, true));
+}
+
+/*
* e1000_write_phy_reg_igp - Write igp PHY register
* @hw: pointer to the HW structure
* @offset: register offset to write to
* @data: data to write at register offset
+ * @locked: semaphore has already been acquired or not
*
* Acquires semaphore, if necessary, then writes the data to PHY register
* at the offset. Release any acquired semaphores before exiting.
*/
-s32
-e1000_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data)
+static s32
+__e1000_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data,
+ bool locked)
{
s32 ret_val = E1000_SUCCESS;
DEBUGFUNC("e1000_write_phy_reg_igp");
- if (!(hw->phy.ops.acquire))
- goto out;
+ if (!locked) {
+ if (!(hw->phy.ops.acquire))
+ goto out;
- ret_val = hw->phy.ops.acquire(hw);
- if (ret_val)
- goto out;
+ ret_val = hw->phy.ops.acquire(hw);
+ if (ret_val)
+ goto out;
+ }
if (offset > MAX_PHY_MULTI_PAGE_REG) {
ret_val = e1000_write_phy_reg_mdic(hw,
- IGP01E1000_PHY_PAGE_SELECT,
- (u16)offset);
- if (ret_val) {
- hw->phy.ops.release(hw);
- goto out;
- }
+ IGP01E1000_PHY_PAGE_SELECT, (u16)offset);
+ if (ret_val)
+ goto release;
}
- ret_val = e1000_write_phy_reg_mdic(hw,
- MAX_PHY_REG_ADDRESS & offset,
+ ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
data);
- hw->phy.ops.release(hw);
+release:
+ if (!locked)
+ hw->phy.ops.release(hw);
out:
return (ret_val);
}
/*
- * e1000_read_kmrn_reg_generic - Read kumeran register
+ * e1000_write_phy_reg_igp - Write igp PHY register
+ * @hw: pointer to the HW structure
+ * @offset: register offset to write to
+ * @data: data to write at register offset
+ *
+ * Acquires semaphore then writes the data to PHY register
+ * at the offset. Release any acquired semaphores before exiting.
+ */
+s32
+e1000_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data)
+{
+ return (__e1000_write_phy_reg_igp(hw, offset, data, false));
+}
+
+/*
+ * e1000_write_phy_reg_igp_locked - Write igp PHY register
+ * @hw: pointer to the HW structure
+ * @offset: register offset to write to
+ * @data: data to write at register offset
+ *
+ * Writes the data to PHY register at the offset.
+ * Assumes semaphore already acquired.
+ */
+s32
+e1000_write_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 data)
+{
+ return (__e1000_write_phy_reg_igp(hw, offset, data, true));
+}
+
+/*
+ * __e1000_read_kmrn_reg - Read kumeran register
* @hw: pointer to the HW structure
* @offset: register offset to be read
* @data: pointer to the read data
+ * @locked: semaphore has already been acquired or not
*
- * Acquires semaphore, if necessary. Then reads the PHY register at offset
- * using the kumeran interface. The information retrieved is stored in data.
+ * Acquires semaphore, if necessary. Then reads the PHY register at offset
+ * using the kumeran interface. The information retrieved is stored in data.
* Release any acquired semaphores before exiting.
*/
-s32
-e1000_read_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 *data)
+static s32
+__e1000_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data, bool locked)
{
u32 kmrnctrlsta;
s32 ret_val = E1000_SUCCESS;
- DEBUGFUNC("e1000_read_kmrn_reg_generic");
+ DEBUGFUNC("__e1000_read_kmrn_reg");
- if (!(hw->phy.ops.acquire))
- goto out;
+ if (!locked) {
+ if (!(hw->phy.ops.acquire))
+ goto out;
- ret_val = hw->phy.ops.acquire(hw);
- if (ret_val)
- goto out;
+ ret_val = hw->phy.ops.acquire(hw);
+ if (ret_val)
+ goto out;
+ }
kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) &
E1000_KMRNCTRLSTA_OFFSET) | E1000_KMRNCTRLSTA_REN;
@@ -540,49 +619,117 @@ e1000_read_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 *data)
kmrnctrlsta = E1000_READ_REG(hw, E1000_KMRNCTRLSTA);
*data = (u16)kmrnctrlsta;
- hw->phy.ops.release(hw);
+ if (!locked)
+ hw->phy.ops.release(hw);
out:
return (ret_val);
}
/*
- * e1000_write_kmrn_reg_generic - Write kumeran register
+ * e1000_read_kmrn_reg_generic - Read kumeran register
+ * @hw: pointer to the HW structure
+ * @offset: register offset to be read
+ * @data: pointer to the read data
+ *
+ * Acquires semaphore then reads the PHY register at offset using the
+ * kumeran interface. The information retrieved is stored in data.
+ * Release the acquired semaphore before exiting.
+ */
+s32
+e1000_read_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 *data)
+{
+ return (__e1000_read_kmrn_reg(hw, offset, data, false));
+}
+
+/*
+ * e1000_read_kmrn_reg_locked - Read kumeran register
+ * @hw: pointer to the HW structure
+ * @offset: register offset to be read
+ * @data: pointer to the read data
+ *
+ * Reads the PHY register at offset using the kumeran interface. The
+ * information retrieved is stored in data.
+ * Assumes semaphore already acquired.
+ */
+s32
+e1000_read_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 *data)
+{
+ return (__e1000_read_kmrn_reg(hw, offset, data, true));
+}
+
+/*
+ * __e1000_write_kmrn_reg - Write kumeran register
* @hw: pointer to the HW structure
* @offset: register offset to write to
* @data: data to write at register offset
+ * @locked: semaphore has already been acquired or not
*
* Acquires semaphore, if necessary. Then write the data to PHY register
* at the offset using the kumeran interface. Release any acquired semaphores
* before exiting.
*/
-s32
-e1000_write_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 data)
+static s32
+__e1000_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data, bool locked)
{
u32 kmrnctrlsta;
s32 ret_val = E1000_SUCCESS;
DEBUGFUNC("e1000_write_kmrn_reg_generic");
- if (!(hw->phy.ops.acquire))
- goto out;
+ if (!locked) {
+ if (!(hw->phy.ops.acquire))
+ goto out;
- ret_val = hw->phy.ops.acquire(hw);
- if (ret_val)
- goto out;
+ ret_val = hw->phy.ops.acquire(hw);
+ if (ret_val)
+ goto out;
+ }
kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) &
E1000_KMRNCTRLSTA_OFFSET) | data;
E1000_WRITE_REG(hw, E1000_KMRNCTRLSTA, kmrnctrlsta);
usec_delay(2);
- hw->phy.ops.release(hw);
+
+ if (!locked)
+ hw->phy.ops.release(hw);
out:
return (ret_val);
}
/*
+ * e1000_write_kmrn_reg_generic - Write kumeran register
+ * @hw: pointer to the HW structure
+ * @offset: register offset to write to
+ * @data: data to write at register offset
+ *
+ * Acquires semaphore then writes the data to the PHY register at the offset
+ * using the kumeran interface. Release the acquired semaphore before exiting.
+ */
+s32
+e1000_write_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 data)
+{
+ return (__e1000_write_kmrn_reg(hw, offset, data, false));
+}
+
+/*
+ * e1000_write_kmrn_reg_locked - Write kumeran register
+ * @hw: pointer to the HW structure
+ * @offset: register offset to write to
+ * @data: data to write at register offset
+ *
+ * Write the data to PHY register at the offset using the kumeran interface.
+ * Assumes semaphore already acquired.
+ */
+s32
+e1000_write_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 data)
+{
+ return (__e1000_write_kmrn_reg(hw, offset, data, true));
+}
+
+/*
* e1000_copper_link_setup_82577 - Setup 82577 PHY for copper link
* @hw: pointer to the HW structure
*
@@ -1863,8 +2010,7 @@ e1000_phy_has_link_generic(struct e1000_hw *hw, u32 iterations,
*/
usec_delay(usec_interval);
}
- ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS,
- &phy_status);
+ ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status);
if (ret_val)
break;
if (phy_status & MII_SR_LINK_STATUS)
@@ -2460,15 +2606,16 @@ e1000_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data)
DEBUGFUNC("e1000_write_phy_reg_bm");
+ ret_val = hw->phy.ops.acquire(hw);
+ if (ret_val)
+ goto out;
+
/* Page 800 works differently than the rest so it has its own func */
if (page == BM_WUC_PAGE) {
ret_val = e1000_access_phy_wakeup_reg_bm(hw,
offset, &data, false);
goto out;
}
- ret_val = hw->phy.ops.acquire(hw);
- if (ret_val)
- goto out;
hw->phy.addr = e1000_get_phy_addr_for_bm_page(page, offset);
@@ -2489,19 +2636,16 @@ e1000_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data)
/* Page is shifted left, PHY expects (page x 32) */
ret_val = e1000_write_phy_reg_mdic(hw, page_select,
(page << page_shift));
- if (ret_val) {
- hw->phy.ops.release(hw);
+ if (ret_val)
goto out;
- }
}
ret_val = e1000_write_phy_reg_mdic(hw,
MAX_PHY_REG_ADDRESS & offset,
data);
- hw->phy.ops.release(hw);
-
out:
+ hw->phy.ops.release(hw);
return (ret_val);
}
@@ -2525,15 +2669,16 @@ e1000_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data)
DEBUGFUNC("e1000_read_phy_reg_bm");
+ ret_val = hw->phy.ops.acquire(hw);
+ if (ret_val)
+ goto out;
+
/* Page 800 works differently than the rest so it has its own func */
if (page == BM_WUC_PAGE) {
ret_val = e1000_access_phy_wakeup_reg_bm(hw,
offset, data, true);
goto out;
}
- ret_val = hw->phy.ops.acquire(hw);
- if (ret_val)
- goto out;
hw->phy.addr = e1000_get_phy_addr_for_bm_page(page, offset);
@@ -2554,18 +2699,16 @@ e1000_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data)
/* Page is shifted left, PHY expects (page x 32) */
ret_val = e1000_write_phy_reg_mdic(hw, page_select,
(page << page_shift));
- if (ret_val) {
- hw->phy.ops.release(hw);
+ if (ret_val)
goto out;
- }
}
ret_val = e1000_read_phy_reg_mdic(hw,
MAX_PHY_REG_ADDRESS & offset,
data);
- hw->phy.ops.release(hw);
out:
+ hw->phy.ops.release(hw);
return (ret_val);
}
@@ -2587,6 +2730,10 @@ e1000_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data)
DEBUGFUNC("e1000_write_phy_reg_bm2");
+ ret_val = hw->phy.ops.acquire(hw);
+ if (ret_val)
+ goto out;
+
/* Page 800 works differently than the rest so it has its own func */
if (page == BM_WUC_PAGE) {
ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data,
@@ -2594,10 +2741,6 @@ e1000_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data)
goto out;
}
- ret_val = hw->phy.ops.acquire(hw);
- if (ret_val)
- goto out;
-
hw->phy.addr = 1;
if (offset > MAX_PHY_MULTI_PAGE_REG) {
@@ -2606,17 +2749,15 @@ e1000_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data)
ret_val = e1000_write_phy_reg_mdic(hw, BM_PHY_PAGE_SELECT,
page);
- if (ret_val) {
- hw->phy.ops.release(hw);
+ if (ret_val)
goto out;
- }
}
ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
data);
- hw->phy.ops.release(hw);
out:
+ hw->phy.ops.release(hw);
return (ret_val);
}
@@ -2637,6 +2778,10 @@ e1000_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data)
DEBUGFUNC("e1000_write_phy_reg_bm2");
+ ret_val = hw->phy.ops.acquire(hw);
+ if (ret_val)
+ goto out;
+
/* Page 800 works differently than the rest so it has its own func */
if (page == BM_WUC_PAGE) {
ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data,
@@ -2644,10 +2789,6 @@ e1000_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data)
goto out;
}
- ret_val = hw->phy.ops.acquire(hw);
- if (ret_val)
- goto out;
-
hw->phy.addr = 1;
if (offset > MAX_PHY_MULTI_PAGE_REG) {
@@ -2655,18 +2796,15 @@ e1000_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data)
ret_val = e1000_write_phy_reg_mdic(hw, BM_PHY_PAGE_SELECT,
page);
- if (ret_val) {
- hw->phy.ops.release(hw);
+ if (ret_val)
goto out;
- }
}
ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
data);
- hw->phy.ops.release(hw);
-
out:
+ hw->phy.ops.release(hw);
return (ret_val);
}
@@ -2686,6 +2824,8 @@ out:
* 3) Write the address using the address opcode (0x11)
* 4) Read or write the data using the data opcode (0x12)
* 5) Restore 769_17.2 to its original value
+ *
+ * Assumes semaphore already acquired.
*/
static s32
e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw,
@@ -2694,7 +2834,6 @@ e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw,
s32 ret_val;
u16 reg = BM_PHY_REG_NUM(offset);
u16 phy_reg = 0;
- u8 phy_acquired = 1;
DEBUGFUNC("e1000_access_phy_wakeup_reg_bm");
@@ -2704,13 +2843,6 @@ e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw,
E1000_PHY_CTRL_GBE_DISABLE)))
DEBUGOUT("Attempting to access page 800 while gig enabled.\n");
- ret_val = hw->phy.ops.acquire(hw);
- if (ret_val) {
- DEBUGOUT("Could not acquire PHY\n");
- phy_acquired = 0;
- goto out;
- }
-
/* All operations in this function are phy address 1 */
hw->phy.addr = 1;
@@ -2781,8 +2913,6 @@ e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw,
}
out:
- if (phy_acquired == 1)
- hw->phy.ops.release(hw);
return (ret_val);
}
@@ -2825,16 +2955,19 @@ e1000_power_down_phy_copper(struct e1000_hw *hw)
msec_delay(1);
}
+/*
+ * e1000_set_mdio_slow_mode_hv - Set slow MDIO access mode
+ * @hw: pointer to the HW structure
+ * @slow: true for slow mode, false for normal mode
+ *
+ * Assumes semaphore already acquired.
+ */
s32
e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw, bool slow)
{
s32 ret_val = E1000_SUCCESS;
u16 data = 0;
- ret_val = hw->phy.ops.acquire(hw);
- if (ret_val)
- return (ret_val);
-
/* Set MDIO mode - page 769, register 16: 0x2580==slow, 0x2180==fast */
hw->phy.addr = 1;
ret_val = e1000_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT,
@@ -2853,22 +2986,23 @@ e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw, bool slow)
ret_val = e1000_read_phy_reg_mdic(hw, BM_CS_CTRL1, &data);
out:
- hw->phy.ops.release(hw);
return (ret_val);
}
/*
- * e1000_read_phy_reg_hv - Read HV PHY register
+ * __e1000_read_phy_reg_hv - Read HV PHY register
* @hw: pointer to the HW structure
* @offset: register offset to be read
* @data: pointer to the read data
+ * @locked: semaphore has already been acquired or not
*
* Acquires semaphore, if necessary, then reads the PHY register at offset
- * and storing the retrieved information in data. Release any acquired
+ * and stores the retrieved information in data. Release any acquired
* semaphore before exiting.
*/
-s32
-e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data)
+static s32
+__e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data,
+ bool locked)
{
s32 ret_val;
u16 page = BM_PHY_REG_PAGE(offset);
@@ -2877,6 +3011,12 @@ e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data)
DEBUGFUNC("e1000_read_phy_reg_hv");
+ if (!locked) {
+ ret_val = hw->phy.ops.acquire(hw);
+ if (ret_val)
+ return (ret_val);
+ }
+
/* Workaround failure in MDIO access while cable is disconnected */
if ((hw->phy.type == e1000_phy_82577) &&
!(E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_LU)) {
@@ -2900,10 +3040,6 @@ e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data)
goto out;
}
- ret_val = hw->phy.ops.acquire(hw);
- if (ret_val)
- goto out;
-
hw->phy.addr = e1000_get_phy_addr_for_hv_page(page);
if (page == HV_INTC_FC_PAGE_START)
@@ -2911,51 +3047,86 @@ e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data)
if (reg > MAX_PHY_MULTI_PAGE_REG) {
u32 phy_addr = hw->phy.addr;
+
hw->phy.addr = 1;
/* Page is shifted left, PHY expects (page x 32) */
ret_val = e1000_write_phy_reg_mdic(hw,
- IGP01E1000_PHY_PAGE_SELECT,
- (page << IGP_PAGE_SHIFT));
+ IGP01E1000_PHY_PAGE_SELECT, (page << IGP_PAGE_SHIFT));
hw->phy.addr = phy_addr;
-
- if (ret_val) {
- hw->phy.ops.release(hw);
- goto out;
- }
}
- ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg,
- data);
- hw->phy.ops.release(hw);
-
+ ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg, data);
out:
/* Revert to MDIO fast mode, if applicable */
if ((hw->phy.type == e1000_phy_82577) && in_slow_mode)
ret_val = e1000_set_mdio_slow_mode_hv(hw, false);
+ if (!locked)
+ hw->phy.ops.release(hw);
+
return (ret_val);
}
/*
- * e1000_write_phy_reg_hv - Write HV PHY register
+ * e1000_read_phy_reg_hv - Read HV PHY register
+ * @hw: pointer to the HW structure
+ * @offset: register offset to be read
+ * @data: pointer to the read data
+ *
+ * Acquires semaphore then reads the PHY register at offset and stores
+ * the retrieved information in data. Release the acquired semaphore
+ * before exiting.
+ */
+s32
+e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data)
+{
+ return (__e1000_read_phy_reg_hv(hw, offset, data, false));
+}
+
+/*
+ * e1000_read_phy_reg_hv_locked - Read HV PHY register
+ * @hw: pointer to the HW structure
+ * @offset: register offset to be read
+ * @data: pointer to the read data
+ *
+ * Reads the PHY register at offset and stores the retrieved information
+ * in data. Assumes semaphore already acquired.
+ */
+s32
+e1000_read_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 *data)
+{
+ return (__e1000_read_phy_reg_hv(hw, offset, data, true));
+}
+
+/*
+ * __e1000_write_phy_reg_hv - Write HV PHY register
* @hw: pointer to the HW structure
* @offset: register offset to write to
* @data: data to write at register offset
+ * @locked: semaphore has already been acquired or not
*
* Acquires semaphore, if necessary, then writes the data to PHY register
* at the offset. Release any acquired semaphores before exiting.
*/
-s32
-e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data)
+static s32
+__e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data,
+ bool locked)
{
s32 ret_val;
u16 page = BM_PHY_REG_PAGE(offset);
u16 reg = BM_PHY_REG_NUM(offset);
bool in_slow_mode = false;
+ struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
DEBUGFUNC("e1000_write_phy_reg_hv");
+ if (!locked) {
+ ret_val = hw->phy.ops.acquire(hw);
+ if (ret_val)
+ return (ret_val);
+ }
+
/* Workaround failure in MDIO access while cable is disconnected */
if ((hw->phy.type == e1000_phy_82577) &&
!(E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_LU)) {
@@ -2979,11 +3150,9 @@ e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data)
goto out;
}
- ret_val = hw->phy.ops.acquire(hw);
- if (ret_val)
- goto out;
-
- hw->phy.addr = e1000_get_phy_addr_for_hv_page(page);
+ /* The LCD Config workaround provides the phy address to use */
+ if (dev_spec->nvm_lcd_config_enabled == false)
+ hw->phy.addr = e1000_get_phy_addr_for_hv_page(page);
if (page == HV_INTC_FC_PAGE_START)
page = 0;
@@ -2998,46 +3167,68 @@ e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data)
((MAX_PHY_REG_ADDRESS & reg) == 0) &&
(data & (1 << 11))) {
u16 data2 = 0x7EFF;
- hw->phy.ops.release(hw);
ret_val = e1000_access_phy_debug_regs_hv(hw, (1 << 6) | 0x3,
&data2, false);
if (ret_val)
goto out;
-
- ret_val = hw->phy.ops.acquire(hw);
- if (ret_val)
- goto out;
}
if (reg > MAX_PHY_MULTI_PAGE_REG) {
u32 phy_addr = hw->phy.addr;
+
hw->phy.addr = 1;
/* Page is shifted left, PHY expects (page x 32) */
ret_val = e1000_write_phy_reg_mdic(hw,
- IGP01E1000_PHY_PAGE_SELECT,
- (page << IGP_PAGE_SHIFT));
+ IGP01E1000_PHY_PAGE_SELECT, (page << IGP_PAGE_SHIFT));
hw->phy.addr = phy_addr;
-
- if (ret_val) {
- hw->phy.ops.release(hw);
- goto out;
- }
}
ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg,
data);
- hw->phy.ops.release(hw);
out:
/* Revert to MDIO fast mode, if applicable */
if ((hw->phy.type == e1000_phy_82577) && in_slow_mode)
ret_val = e1000_set_mdio_slow_mode_hv(hw, false);
+ if (!locked)
+ hw->phy.ops.release(hw);
+
return (ret_val);
}
/*
+ * e1000_write_phy_reg_hv - Write HV PHY register
+ * @hw: pointer to the HW structure
+ * @offset: register offset to write to
+ * @data: data to write at register offset
+ *
+ * Acquires semaphore then writes the data to PHY register at the offset.
+ * Release the acquired semaphores before exiting.
+ */
+s32
+e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data)
+{
+ return (__e1000_write_phy_reg_hv(hw, offset, data, false));
+}
+
+/*
+ * e1000_write_phy_reg_hv_locked - Write HV PHY register
+ * @hw: pointer to the HW structure
+ * @offset: register offset to write to
+ * @data: data to write at register offset
+ *
+ * Writes the data to PHY register at the offset. Assumes semaphore
+ * already acquired.
+ */
+s32
+e1000_write_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 data)
+{
+ return (__e1000_write_phy_reg_hv(hw, offset, data, true));
+}
+
+/*
* e1000_get_phy_addr_for_hv_page - Get PHY adrress based on page
* @page: page to be accessed
*/
@@ -3059,10 +3250,9 @@ e1000_get_phy_addr_for_hv_page(u32 page)
* @data: pointer to the data to be read or written
* @read: determines if operation is read or written
*
- * Acquires semaphore, if necessary, then reads the PHY register at offset
- * and storing the retreived information in data. Release any acquired
- * semaphores before exiting. Note that the procedure to read these regs
- * uses the address port and data port to read/write.
+ * Reads the PHY register at offset and stores the retreived information
+ * in data. Assumes semaphore already acquired. Note that the procedure
+ * to read these regs uses the address port and data port to read/write.
*/
static s32
e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset,
@@ -3071,7 +3261,6 @@ e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset,
s32 ret_val;
u32 addr_reg = 0;
u32 data_reg = 0;
- u8 phy_acquired = 1;
DEBUGFUNC("e1000_access_phy_debug_regs_hv");
@@ -3080,13 +3269,6 @@ e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset,
I82578_ADDR_REG : I82577_ADDR_REG;
data_reg = addr_reg + 1;
- ret_val = hw->phy.ops.acquire(hw);
- if (ret_val) {
- DEBUGOUT("Could not acquire PHY\n");
- phy_acquired = 0;
- goto out;
- }
-
/* All operations in this function are phy address 2 */
hw->phy.addr = 2;
@@ -3109,8 +3291,6 @@ e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset,
}
out:
- if (phy_acquired == 1)
- hw->phy.ops.release(hw);
return (ret_val);
}
diff --git a/usr/src/uts/common/io/e1000g/e1000_phy.h b/usr/src/uts/common/io/e1000g/e1000_phy.h
index 48423fa88b..e052cabeb1 100644
--- a/usr/src/uts/common/io/e1000g/e1000_phy.h
+++ b/usr/src/uts/common/io/e1000g/e1000_phy.h
@@ -24,7 +24,7 @@
*/
/*
- * IntelVersion: 1.70 v3-1-3_2009-8-20
+ * IntelVersion: 1.74 v3-1-10-1_2009-9-18_Release14-6
*/
#ifndef _E1000_PHY_H_
#define _E1000_PHY_H_
@@ -61,13 +61,17 @@ s32 e1000_phy_hw_reset_generic(struct e1000_hw *hw);
s32 e1000_phy_reset_dsp_generic(struct e1000_hw *hw);
s32 e1000_phy_setup_autoneg(struct e1000_hw *hw);
s32 e1000_read_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 *data);
+s32 e1000_read_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 *data);
s32 e1000_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data);
+s32 e1000_read_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 *data);
s32 e1000_read_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 *data);
s32 e1000_set_d3_lplu_state_generic(struct e1000_hw *hw, bool active);
s32 e1000_setup_copper_link_generic(struct e1000_hw *hw);
s32 e1000_wait_autoneg_generic(struct e1000_hw *hw);
s32 e1000_write_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 data);
+s32 e1000_write_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 data);
s32 e1000_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data);
+s32 e1000_write_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 data);
s32 e1000_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data);
s32 e1000_phy_reset_dsp(struct e1000_hw *hw);
s32 e1000_phy_has_link_generic(struct e1000_hw *hw, u32 iterations,
@@ -84,7 +88,9 @@ void e1000_power_down_phy_copper(struct e1000_hw *hw);
s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data);
s32 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data);
s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data);
+s32 e1000_read_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 *data);
s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data);
+s32 e1000_write_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 data);
s32 e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw, bool slow);
s32 e1000_link_stall_workaround_hv(struct e1000_hw *hw);
s32 e1000_copper_link_setup_82577(struct e1000_hw *hw);
@@ -173,6 +179,13 @@ s32 e1000_get_cable_length_82577(struct e1000_hw *hw);
#define BM_CS_STATUS_SPEED_MASK 0xC000
#define BM_CS_STATUS_SPEED_1000 0x8000
+/* 82577 Mobile Phy Status Register */
+#define HV_M_STATUS 26
+#define HV_M_STATUS_AUTONEG_COMPLETE 0x1000
+#define HV_M_STATUS_SPEED_MASK 0x0300
+#define HV_M_STATUS_SPEED_1000 0x0200
+#define HV_M_STATUS_LINK_UP 0x0040
+
#define IGP01E1000_PHY_PCS_INIT_REG 0x00B4
#define IGP01E1000_PHY_POLARITY_MASK 0x0078
@@ -219,8 +232,7 @@ s32 e1000_get_cable_length_82577(struct e1000_hw *hw);
#define E1000_KMRNCTRLSTA_INBAND_PARAM 0x9 /* Kumeran InBand Parameters */
#define E1000_KMRNCTRLSTA_DIAG_NELPBK 0x1000 /* Nearend Loopback mode */
#define E1000_KMRNCTRLSTA_K1_CONFIG 0x7
-#define E1000_KMRNCTRLSTA_K1_ENABLE 0x140E
-#define E1000_KMRNCTRLSTA_K1_DISABLE 0x1400
+#define E1000_KMRNCTRLSTA_K1_ENABLE 0x0002
#define IFE_PHY_EXTENDED_STATUS_CONTROL 0x10
#define IFE_PHY_SPECIAL_CONTROL 0x11 /* 100BaseTx PHY Special Control */
diff --git a/usr/src/uts/common/io/e1000g/e1000_regs.h b/usr/src/uts/common/io/e1000g/e1000_regs.h
index af6529c281..c7a350a619 100644
--- a/usr/src/uts/common/io/e1000g/e1000_regs.h
+++ b/usr/src/uts/common/io/e1000g/e1000_regs.h
@@ -24,7 +24,7 @@
*/
/*
- * IntelVersion: 1.76 v3-1-3_2009-8-20
+ * IntelVersion: 1.76 v3-1-10-1_2009-9-18_Release14-6
*/
#ifndef _E1000_REGS_H_
#define _E1000_REGS_H_
diff --git a/usr/src/uts/common/io/e1000g/e1000g_main.c b/usr/src/uts/common/io/e1000g/e1000g_main.c
index 5dbce69bd2..01dad50d1f 100644
--- a/usr/src/uts/common/io/e1000g/e1000g_main.c
+++ b/usr/src/uts/common/io/e1000g/e1000g_main.c
@@ -46,7 +46,7 @@
static char ident[] = "Intel PRO/1000 Ethernet";
static char e1000g_string[] = "Intel(R) PRO/1000 Network Connection";
-static char e1000g_version[] = "Driver Ver. 5.3.16";
+static char e1000g_version[] = "Driver Ver. 5.3.17";
/*
* Proto types for DDI entry points