summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/io
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/common/io')
-rw-r--r--usr/src/uts/common/io/e1000api/README.illumos22
-rw-r--r--usr/src/uts/common/io/e1000api/e1000_80003es2lan.c35
-rw-r--r--usr/src/uts/common/io/e1000api/e1000_80003es2lan.h2
-rw-r--r--usr/src/uts/common/io/e1000api/e1000_82540.c12
-rw-r--r--usr/src/uts/common/io/e1000api/e1000_82541.c299
-rw-r--r--usr/src/uts/common/io/e1000api/e1000_82541.h100
-rw-r--r--usr/src/uts/common/io/e1000api/e1000_82542.c44
-rw-r--r--usr/src/uts/common/io/e1000api/e1000_82543.c153
-rw-r--r--usr/src/uts/common/io/e1000api/e1000_82543.h28
-rw-r--r--usr/src/uts/common/io/e1000api/e1000_82571.c2
-rw-r--r--usr/src/uts/common/io/e1000api/e1000_82571.h2
-rw-r--r--usr/src/uts/common/io/e1000api/e1000_82575.c175
-rw-r--r--usr/src/uts/common/io/e1000api/e1000_82575.h16
-rw-r--r--usr/src/uts/common/io/e1000api/e1000_api.c10
-rw-r--r--usr/src/uts/common/io/e1000api/e1000_api.h18
-rw-r--r--usr/src/uts/common/io/e1000api/e1000_defines.h29
-rw-r--r--usr/src/uts/common/io/e1000api/e1000_hw.h20
-rw-r--r--usr/src/uts/common/io/e1000api/e1000_i210.c32
-rw-r--r--usr/src/uts/common/io/e1000api/e1000_i210.h2
-rw-r--r--usr/src/uts/common/io/e1000api/e1000_ich8lan.c951
-rw-r--r--usr/src/uts/common/io/e1000api/e1000_ich8lan.h33
-rw-r--r--usr/src/uts/common/io/e1000api/e1000_mac.c2
-rw-r--r--usr/src/uts/common/io/e1000api/e1000_mac.h4
-rw-r--r--usr/src/uts/common/io/e1000api/e1000_manage.c3
-rw-r--r--usr/src/uts/common/io/e1000api/e1000_manage.h2
-rw-r--r--usr/src/uts/common/io/e1000api/e1000_mbx.c38
-rw-r--r--usr/src/uts/common/io/e1000api/e1000_mbx.h2
-rw-r--r--usr/src/uts/common/io/e1000api/e1000_nvm.c2
-rw-r--r--usr/src/uts/common/io/e1000api/e1000_nvm.h4
-rw-r--r--usr/src/uts/common/io/e1000api/e1000_phy.c21
-rw-r--r--usr/src/uts/common/io/e1000api/e1000_phy.h2
-rw-r--r--usr/src/uts/common/io/e1000api/e1000_regs.h17
-rw-r--r--usr/src/uts/common/io/e1000api/e1000_vf.c2
-rw-r--r--usr/src/uts/common/io/e1000api/e1000_vf.h2
-rw-r--r--usr/src/uts/common/io/e1000g/e1000_osdep.h25
-rw-r--r--usr/src/uts/common/io/e1000g/e1000g_main.c85
-rw-r--r--usr/src/uts/common/io/e1000g/e1000g_rx.c36
-rw-r--r--usr/src/uts/common/io/e1000g/e1000g_sw.h19
-rw-r--r--usr/src/uts/common/io/e1000g/e1000g_tx.c41
-rw-r--r--usr/src/uts/common/io/e1000g/e1000g_workarounds.c13
-rw-r--r--usr/src/uts/common/io/igb/igb_gld.c6
-rw-r--r--usr/src/uts/common/io/igb/igb_main.c9
42 files changed, 1717 insertions, 603 deletions
diff --git a/usr/src/uts/common/io/e1000api/README.illumos b/usr/src/uts/common/io/e1000api/README.illumos
index 7dfcbd33b7..b4335b1470 100644
--- a/usr/src/uts/common/io/e1000api/README.illumos
+++ b/usr/src/uts/common/io/e1000api/README.illumos
@@ -71,33 +71,11 @@ struct e1000_dev_spec_82541 {
u32 tx_fifo_head;
u32 tx_fifo_start;
u32 tx_fifo_size;
- u16 dsp_reset_counter;
u16 spd_default;
bool phy_init_script;
bool ttl_workaround;
};
-Similarly in e1000_82541.h you must make sure the following macros and external
-function declarations are present:
-
-#define E1000_FIFO_MULTIPLIER 0x80
-#define E1000_FIFO_HDR_SIZE 0x10
-#define E1000_FIFO_GRANULARITY 0x10
-#define E1000_FIFO_PAD_82547 0x3E0
-#define E1000_ERR_FIFO_WRAP 8
-
-#define DSP_RESET_ENABLE 0x0
-#define DSP_RESET_DISABLE 0x2
-#define E1000_MAX_DSP_RESETS 10
-
-#define E1000_ROUNDUP(size, unit) (((size) + (unit) - 1) & ~((unit) - 1))
-
-s32 e1000_fifo_workaround_82547(struct e1000_hw *hw, u16 length);
-void e1000_update_tx_fifo_head_82547(struct e1000_hw *hw, u32 length);
-void e1000_set_ttl_workaround_state_82541(struct e1000_hw *hw, bool state);
-bool e1000_ttl_workaround_enabled_82541(struct e1000_hw *hw);
-s32 e1000_igp_ttl_workaround_82547(struct e1000_hw *hw);
-
# EEE
By default we disable all support for EEE. To cause this to happen you must
diff --git a/usr/src/uts/common/io/e1000api/e1000_80003es2lan.c b/usr/src/uts/common/io/e1000api/e1000_80003es2lan.c
index 076e02be9b..e7c42d5386 100644
--- a/usr/src/uts/common/io/e1000api/e1000_80003es2lan.c
+++ b/usr/src/uts/common/io/e1000api/e1000_80003es2lan.c
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2013, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -851,11 +851,17 @@ static s32 e1000_reset_hw_80003es2lan(struct e1000_hw *hw)
e1000_release_phy_80003es2lan(hw);
/* Disable IBIST slave mode (far-end loopback) */
- e1000_read_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM,
- &kum_reg_data);
- kum_reg_data |= E1000_KMRNCTRLSTA_IBIST_DISABLE;
- e1000_write_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM,
- kum_reg_data);
+ ret_val = e1000_read_kmrn_reg_80003es2lan(hw,
+ E1000_KMRNCTRLSTA_INBAND_PARAM, &kum_reg_data);
+ if (!ret_val) {
+ kum_reg_data |= E1000_KMRNCTRLSTA_IBIST_DISABLE;
+ ret_val = e1000_write_kmrn_reg_80003es2lan(hw,
+ E1000_KMRNCTRLSTA_INBAND_PARAM,
+ kum_reg_data);
+ if (ret_val)
+ DEBUGOUT("Error disabling far-end loopback\n");
+ } else
+ DEBUGOUT("Error disabling far-end loopback\n");
ret_val = e1000_get_auto_rd_done_generic(hw);
if (ret_val)
@@ -911,11 +917,18 @@ static s32 e1000_init_hw_80003es2lan(struct e1000_hw *hw)
return ret_val;
/* Disable IBIST slave mode (far-end loopback) */
- e1000_read_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM,
- &kum_reg_data);
- kum_reg_data |= E1000_KMRNCTRLSTA_IBIST_DISABLE;
- e1000_write_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM,
- kum_reg_data);
+ ret_val =
+ e1000_read_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM,
+ &kum_reg_data);
+ if (!ret_val) {
+ kum_reg_data |= E1000_KMRNCTRLSTA_IBIST_DISABLE;
+ ret_val = e1000_write_kmrn_reg_80003es2lan(hw,
+ E1000_KMRNCTRLSTA_INBAND_PARAM,
+ kum_reg_data);
+ if (ret_val)
+ DEBUGOUT("Error disabling far-end loopback\n");
+ } else
+ DEBUGOUT("Error disabling far-end loopback\n");
/* Set the transmit descriptor write-back policy */
reg_data = E1000_READ_REG(hw, E1000_TXDCTL(0));
diff --git a/usr/src/uts/common/io/e1000api/e1000_80003es2lan.h b/usr/src/uts/common/io/e1000api/e1000_80003es2lan.h
index 3807e46305..89b15512bf 100644
--- a/usr/src/uts/common/io/e1000api/e1000_80003es2lan.h
+++ b/usr/src/uts/common/io/e1000api/e1000_80003es2lan.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2013, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/usr/src/uts/common/io/e1000api/e1000_82540.c b/usr/src/uts/common/io/e1000api/e1000_82540.c
index 141b92e208..2d03b8ff8e 100644
--- a/usr/src/uts/common/io/e1000api/e1000_82540.c
+++ b/usr/src/uts/common/io/e1000api/e1000_82540.c
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2011, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -66,7 +66,7 @@ static s32 e1000_read_mac_addr_82540(struct e1000_hw *hw);
static s32 e1000_init_phy_params_82540(struct e1000_hw *hw)
{
struct e1000_phy_info *phy = &hw->phy;
- s32 ret_val = E1000_SUCCESS;
+ s32 ret_val;
phy->addr = 1;
phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT;
@@ -329,7 +329,7 @@ static s32 e1000_init_hw_82540(struct e1000_hw *hw)
{
struct e1000_mac_info *mac = &hw->mac;
u32 txdctl, ctrl_ext;
- s32 ret_val = E1000_SUCCESS;
+ s32 ret_val;
u16 i;
DEBUGFUNC("e1000_init_hw_82540");
@@ -411,7 +411,7 @@ static s32 e1000_init_hw_82540(struct e1000_hw *hw)
static s32 e1000_setup_copper_link_82540(struct e1000_hw *hw)
{
u32 ctrl;
- s32 ret_val = E1000_SUCCESS;
+ s32 ret_val;
u16 data;
DEBUGFUNC("e1000_setup_copper_link_82540");
@@ -498,7 +498,7 @@ out:
**/
static s32 e1000_adjust_serdes_amplitude_82540(struct e1000_hw *hw)
{
- s32 ret_val = E1000_SUCCESS;
+ s32 ret_val;
u16 nvm_data;
DEBUGFUNC("e1000_adjust_serdes_amplitude_82540");
@@ -528,7 +528,7 @@ out:
**/
static s32 e1000_set_vco_speed_82540(struct e1000_hw *hw)
{
- s32 ret_val = E1000_SUCCESS;
+ s32 ret_val;
u16 default_page = 0;
u16 phy_data;
diff --git a/usr/src/uts/common/io/e1000api/e1000_82541.c b/usr/src/uts/common/io/e1000api/e1000_82541.c
index 781aa931fb..55d51087b7 100644
--- a/usr/src/uts/common/io/e1000api/e1000_82541.c
+++ b/usr/src/uts/common/io/e1000api/e1000_82541.c
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2011, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -49,34 +49,34 @@ static s32 e1000_init_mac_params_82541(struct e1000_hw *hw);
static s32 e1000_reset_hw_82541(struct e1000_hw *hw);
static s32 e1000_init_hw_82541(struct e1000_hw *hw);
static s32 e1000_get_link_up_info_82541(struct e1000_hw *hw, u16 *speed,
- u16 *duplex);
+ u16 *duplex);
static s32 e1000_phy_hw_reset_82541(struct e1000_hw *hw);
static s32 e1000_setup_copper_link_82541(struct e1000_hw *hw);
static s32 e1000_check_for_link_82541(struct e1000_hw *hw);
static s32 e1000_get_cable_length_igp_82541(struct e1000_hw *hw);
static s32 e1000_set_d3_lplu_state_82541(struct e1000_hw *hw,
- bool active);
+ bool active);
static s32 e1000_setup_led_82541(struct e1000_hw *hw);
static s32 e1000_cleanup_led_82541(struct e1000_hw *hw);
static void e1000_clear_hw_cntrs_82541(struct e1000_hw *hw);
static s32 e1000_read_mac_addr_82541(struct e1000_hw *hw);
static s32 e1000_config_dsp_after_link_change_82541(struct e1000_hw *hw,
- bool link_up);
+ bool link_up);
static s32 e1000_phy_init_script_82541(struct e1000_hw *hw);
static void e1000_power_down_phy_copper_82541(struct e1000_hw *hw);
-static const u16 e1000_igp_cable_length_table[] =
- { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 10, 10, 10, 10, 10, 10, 10, 20, 20, 20, 20, 20, 25, 25, 25,
- 25, 25, 25, 25, 30, 30, 30, 30, 40, 40, 40, 40, 40, 40, 40, 40,
- 40, 50, 50, 50, 50, 50, 50, 50, 60, 60, 60, 60, 60, 60, 60, 60,
- 60, 70, 70, 70, 70, 70, 70, 80, 80, 80, 80, 80, 80, 90, 90, 90,
- 90, 90, 90, 90, 90, 90, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
- 100, 100, 100, 100, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
- 110, 110, 110, 110, 110, 110, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120};
+static const u16 e1000_igp_cable_length_table[] = {
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 10, 10, 10, 10, 10,
+ 10, 10, 20, 20, 20, 20, 20, 25, 25, 25, 25, 25, 25, 25, 30, 30, 30, 30,
+ 40, 40, 40, 40, 40, 40, 40, 40, 40, 50, 50, 50, 50, 50, 50, 50, 60, 60,
+ 60, 60, 60, 60, 60, 60, 60, 70, 70, 70, 70, 70, 70, 80, 80, 80, 80, 80,
+ 80, 90, 90, 90, 90, 90, 90, 90, 90, 90, 100, 100, 100, 100, 100, 100,
+ 100, 100, 100, 100, 100, 100, 100, 100, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 120, 120,
+ 120, 120, 120, 120, 120, 120, 120, 120};
#define IGP01E1000_AGC_LENGTH_TABLE_SIZE \
- (sizeof(e1000_igp_cable_length_table) / \
- sizeof(e1000_igp_cable_length_table[0]))
+ (sizeof(e1000_igp_cable_length_table) / \
+ sizeof(e1000_igp_cable_length_table[0]))
/**
* e1000_init_phy_params_82541 - Init PHY func ptrs.
@@ -85,27 +85,27 @@ static const u16 e1000_igp_cable_length_table[] =
static s32 e1000_init_phy_params_82541(struct e1000_hw *hw)
{
struct e1000_phy_info *phy = &hw->phy;
- s32 ret_val = E1000_SUCCESS;
+ s32 ret_val;
DEBUGFUNC("e1000_init_phy_params_82541");
- phy->addr = 1;
- phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT;
- phy->reset_delay_us = 10000;
- phy->type = e1000_phy_igp;
+ phy->addr = 1;
+ phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT;
+ phy->reset_delay_us = 10000;
+ phy->type = e1000_phy_igp;
/* Function Pointers */
- phy->ops.check_polarity = e1000_check_polarity_igp;
- phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_igp;
- phy->ops.get_cable_length = e1000_get_cable_length_igp_82541;
- phy->ops.get_cfg_done = e1000_get_cfg_done_generic;
- phy->ops.get_info = e1000_get_phy_info_igp;
- phy->ops.read_reg = e1000_read_phy_reg_igp;
- phy->ops.reset = e1000_phy_hw_reset_82541;
- phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_82541;
- phy->ops.write_reg = e1000_write_phy_reg_igp;
- phy->ops.power_up = e1000_power_up_phy_copper;
- phy->ops.power_down = e1000_power_down_phy_copper_82541;
+ phy->ops.check_polarity = e1000_check_polarity_igp;
+ phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_igp;
+ phy->ops.get_cable_length = e1000_get_cable_length_igp_82541;
+ phy->ops.get_cfg_done = e1000_get_cfg_done_generic;
+ phy->ops.get_info = e1000_get_phy_info_igp;
+ phy->ops.read_reg = e1000_read_phy_reg_igp;
+ phy->ops.reset = e1000_phy_hw_reset_82541;
+ phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_82541;
+ phy->ops.write_reg = e1000_write_phy_reg_igp;
+ phy->ops.power_up = e1000_power_up_phy_copper;
+ phy->ops.power_down = e1000_power_down_phy_copper_82541;
ret_val = e1000_get_phy_id(hw);
if (ret_val)
@@ -127,8 +127,8 @@ out:
**/
static s32 e1000_init_nvm_params_82541(struct e1000_hw *hw)
{
- struct e1000_nvm_info *nvm = &hw->nvm;
- s32 ret_val = E1000_SUCCESS;
+ struct e1000_nvm_info *nvm = &hw->nvm;
+ s32 ret_val = E1000_SUCCESS;
u32 eecd = E1000_READ_REG(hw, E1000_EECD);
u16 size;
@@ -152,28 +152,25 @@ static s32 e1000_init_nvm_params_82541(struct e1000_hw *hw)
eecd &= ~E1000_EECD_SIZE;
break;
default:
- nvm->type = eecd & E1000_EECD_TYPE
- ? e1000_nvm_eeprom_spi
- : e1000_nvm_eeprom_microwire;
+ nvm->type = eecd & E1000_EECD_TYPE ? e1000_nvm_eeprom_spi
+ : e1000_nvm_eeprom_microwire;
break;
}
if (nvm->type == e1000_nvm_eeprom_spi) {
- nvm->address_bits = (eecd & E1000_EECD_ADDR_BITS)
- ? 16 : 8;
- nvm->delay_usec = 1;
- nvm->opcode_bits = 8;
- nvm->page_size = (eecd & E1000_EECD_ADDR_BITS)
- ? 32 : 8;
+ nvm->address_bits = (eecd & E1000_EECD_ADDR_BITS) ? 16 : 8;
+ nvm->delay_usec = 1;
+ nvm->opcode_bits = 8;
+ nvm->page_size = (eecd & E1000_EECD_ADDR_BITS) ? 32 : 8;
/* Function Pointers */
- nvm->ops.acquire = e1000_acquire_nvm_generic;
- nvm->ops.read = e1000_read_nvm_spi;
- nvm->ops.release = e1000_release_nvm_generic;
- nvm->ops.update = e1000_update_nvm_checksum_generic;
+ nvm->ops.acquire = e1000_acquire_nvm_generic;
+ nvm->ops.read = e1000_read_nvm_spi;
+ nvm->ops.release = e1000_release_nvm_generic;
+ nvm->ops.update = e1000_update_nvm_checksum_generic;
nvm->ops.valid_led_default = e1000_valid_led_default_generic;
- nvm->ops.validate = e1000_validate_nvm_checksum_generic;
- nvm->ops.write = e1000_write_nvm_spi;
+ nvm->ops.validate = e1000_validate_nvm_checksum_generic;
+ nvm->ops.write = e1000_write_nvm_spi;
/*
* nvm->word_size must be discovered after the pointers
@@ -196,21 +193,19 @@ static s32 e1000_init_nvm_params_82541(struct e1000_hw *hw)
nvm->word_size = 1 << size;
}
} else {
- nvm->address_bits = (eecd & E1000_EECD_ADDR_BITS)
- ? 8 : 6;
- nvm->delay_usec = 50;
- nvm->opcode_bits = 3;
- nvm->word_size = (eecd & E1000_EECD_ADDR_BITS)
- ? 256 : 64;
+ nvm->address_bits = (eecd & E1000_EECD_ADDR_BITS) ? 8 : 6;
+ nvm->delay_usec = 50;
+ nvm->opcode_bits = 3;
+ nvm->word_size = (eecd & E1000_EECD_ADDR_BITS) ? 256 : 64;
/* Function Pointers */
- nvm->ops.acquire = e1000_acquire_nvm_generic;
- nvm->ops.read = e1000_read_nvm_microwire;
- nvm->ops.release = e1000_release_nvm_generic;
- nvm->ops.update = e1000_update_nvm_checksum_generic;
+ nvm->ops.acquire = e1000_acquire_nvm_generic;
+ nvm->ops.read = e1000_read_nvm_microwire;
+ nvm->ops.release = e1000_release_nvm_generic;
+ nvm->ops.update = e1000_update_nvm_checksum_generic;
nvm->ops.valid_led_default = e1000_valid_led_default_generic;
- nvm->ops.validate = e1000_validate_nvm_checksum_generic;
- nvm->ops.write = e1000_write_nvm_microwire;
+ nvm->ops.validate = e1000_validate_nvm_checksum_generic;
+ nvm->ops.write = e1000_write_nvm_microwire;
}
out:
@@ -300,7 +295,7 @@ void e1000_init_function_pointers_82541(struct e1000_hw *hw)
**/
static s32 e1000_reset_hw_82541(struct e1000_hw *hw)
{
- u32 ledctl, ctrl, icr, manc;
+ u32 ledctl, ctrl, manc;
DEBUGFUNC("e1000_reset_hw_82541");
@@ -322,6 +317,7 @@ static s32 e1000_reset_hw_82541(struct e1000_hw *hw)
/* Must reset the Phy before resetting the MAC */
if ((hw->mac.type == e1000_82541) || (hw->mac.type == e1000_82547)) {
E1000_WRITE_REG(hw, E1000_CTRL, (ctrl | E1000_CTRL_PHY_RST));
+ E1000_WRITE_FLUSH(hw);
msec_delay(5);
}
@@ -364,7 +360,7 @@ static s32 e1000_reset_hw_82541(struct e1000_hw *hw)
E1000_WRITE_REG(hw, E1000_IMC, 0xFFFFFFFF);
/* Clear any pending interrupt events. */
- icr = E1000_READ_REG(hw, E1000_ICR);
+ E1000_READ_REG(hw, E1000_ICR);
return E1000_SUCCESS;
}
@@ -390,11 +386,10 @@ static s32 e1000_init_hw_82541(struct e1000_hw *hw)
DEBUGOUT("Error initializing identification LED\n");
/* This is not fatal and we should not stop init due to this */
}
-
+
/* Storing the Speed Power Down value for later use */
- ret_val = hw->phy.ops.read_reg(hw,
- IGP01E1000_GMII_FIFO,
- &dev_spec->spd_default);
+ ret_val = hw->phy.ops.read_reg(hw, IGP01E1000_GMII_FIFO,
+ &dev_spec->spd_default);
if (ret_val)
goto out;
@@ -423,7 +418,7 @@ static s32 e1000_init_hw_82541(struct e1000_hw *hw)
txdctl = E1000_READ_REG(hw, E1000_TXDCTL(0));
txdctl = (txdctl & ~E1000_TXDCTL_WTHRESH) |
- E1000_TXDCTL_FULL_TX_DESC_WB;
+ E1000_TXDCTL_FULL_TX_DESC_WB;
E1000_WRITE_REG(hw, E1000_TXDCTL(0), txdctl);
/*
@@ -447,7 +442,7 @@ out:
* Retrieve the current speed and duplex configuration.
**/
static s32 e1000_get_link_up_info_82541(struct e1000_hw *hw, u16 *speed,
- u16 *duplex)
+ u16 *duplex)
{
struct e1000_phy_info *phy = &hw->phy;
s32 ret_val;
@@ -549,6 +544,7 @@ static s32 e1000_setup_copper_link_82541(struct e1000_hw *hw)
ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
+
/* Earlier revs of the IGP phy require us to force MDI. */
if (hw->mac.type == e1000_82541 || hw->mac.type == e1000_82547) {
dev_spec->dsp_config = e1000_dsp_config_disabled;
@@ -651,9 +647,8 @@ static s32 e1000_check_for_link_82541(struct e1000_hw *hw)
* different link partner.
*/
ret_val = e1000_config_fc_after_link_up_generic(hw);
- if (ret_val) {
+ if (ret_val)
DEBUGOUT("Error configuring flow control\n");
- }
out:
return ret_val;
@@ -671,7 +666,7 @@ out:
* gigabit link is achieved to improve link quality.
**/
static s32 e1000_config_dsp_after_link_change_82541(struct e1000_hw *hw,
- bool link_up)
+ bool link_up)
{
struct e1000_phy_info *phy = &hw->phy;
struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541;
@@ -679,11 +674,11 @@ static s32 e1000_config_dsp_after_link_change_82541(struct e1000_hw *hw,
u32 idle_errs = 0;
u16 phy_data, phy_saved_data, speed, duplex, i;
u16 ffe_idle_err_timeout = FFE_IDLE_ERR_COUNT_TIMEOUT_20;
- u16 dsp_reg_array[IGP01E1000_PHY_CHANNEL_NUM] =
- {IGP01E1000_PHY_AGC_PARAM_A,
- IGP01E1000_PHY_AGC_PARAM_B,
- IGP01E1000_PHY_AGC_PARAM_C,
- IGP01E1000_PHY_AGC_PARAM_D};
+ u16 dsp_reg_array[IGP01E1000_PHY_CHANNEL_NUM] = {
+ IGP01E1000_PHY_AGC_PARAM_A,
+ IGP01E1000_PHY_AGC_PARAM_B,
+ IGP01E1000_PHY_AGC_PARAM_C,
+ IGP01E1000_PHY_AGC_PARAM_D};
DEBUGFUNC("e1000_config_dsp_after_link_change_82541");
@@ -708,16 +703,16 @@ static s32 e1000_config_dsp_after_link_change_82541(struct e1000_hw *hw,
for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) {
ret_val = phy->ops.read_reg(hw,
- dsp_reg_array[i],
- &phy_data);
+ dsp_reg_array[i],
+ &phy_data);
if (ret_val)
goto out;
phy_data &= ~IGP01E1000_PHY_EDAC_MU_INDEX;
ret_val = phy->ops.write_reg(hw,
- dsp_reg_array[i],
- phy_data);
+ dsp_reg_array[i],
+ phy_data);
if (ret_val)
goto out;
}
@@ -737,9 +732,8 @@ static s32 e1000_config_dsp_after_link_change_82541(struct e1000_hw *hw,
for (i = 0; i < ffe_idle_err_timeout; i++) {
usec_delay(1000);
- ret_val = phy->ops.read_reg(hw,
- PHY_1000T_STATUS,
- &phy_data);
+ ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS,
+ &phy_data);
if (ret_val)
goto out;
@@ -748,8 +742,8 @@ static s32 e1000_config_dsp_after_link_change_82541(struct e1000_hw *hw,
dev_spec->ffe_config = e1000_ffe_config_active;
ret_val = phy->ops.write_reg(hw,
- IGP01E1000_PHY_DSP_FFE,
- IGP01E1000_PHY_DSP_FFE_CM_CP);
+ IGP01E1000_PHY_DSP_FFE,
+ IGP01E1000_PHY_DSP_FFE_CM_CP);
if (ret_val)
goto out;
break;
@@ -757,7 +751,7 @@ static s32 e1000_config_dsp_after_link_change_82541(struct e1000_hw *hw,
if (idle_errs)
ffe_idle_err_timeout =
- FFE_IDLE_ERR_COUNT_TIMEOUT_100;
+ FFE_IDLE_ERR_COUNT_TIMEOUT_100;
}
} else {
if (dev_spec->dsp_config == e1000_dsp_config_activated) {
@@ -765,9 +759,8 @@ static s32 e1000_config_dsp_after_link_change_82541(struct e1000_hw *hw,
* Save off the current value of register 0x2F5B
* to be restored at the end of the routines.
*/
- ret_val = phy->ops.read_reg(hw,
- 0x2F5B,
- &phy_saved_data);
+ ret_val = phy->ops.read_reg(hw, 0x2F5B,
+ &phy_saved_data);
if (ret_val)
goto out;
@@ -778,15 +771,14 @@ static s32 e1000_config_dsp_after_link_change_82541(struct e1000_hw *hw,
msec_delay_irq(20);
- ret_val = phy->ops.write_reg(hw,
- 0x0000,
- IGP01E1000_IEEE_FORCE_GIG);
+ ret_val = phy->ops.write_reg(hw, 0x0000,
+ IGP01E1000_IEEE_FORCE_GIG);
if (ret_val)
goto out;
for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) {
ret_val = phy->ops.read_reg(hw,
- dsp_reg_array[i],
- &phy_data);
+ dsp_reg_array[i],
+ &phy_data);
if (ret_val)
goto out;
@@ -794,24 +786,22 @@ static s32 e1000_config_dsp_after_link_change_82541(struct e1000_hw *hw,
phy_data |= IGP01E1000_PHY_EDAC_SIGN_EXT_9_BITS;
ret_val = phy->ops.write_reg(hw,
- dsp_reg_array[i],
- phy_data);
+ dsp_reg_array[i],
+ phy_data);
if (ret_val)
goto out;
}
- ret_val = phy->ops.write_reg(hw,
- 0x0000,
- IGP01E1000_IEEE_RESTART_AUTONEG);
+ ret_val = phy->ops.write_reg(hw, 0x0000,
+ IGP01E1000_IEEE_RESTART_AUTONEG);
if (ret_val)
goto out;
msec_delay_irq(20);
/* Now enable the transmitter */
- ret_val = phy->ops.write_reg(hw,
- 0x2F5B,
- phy_saved_data);
+ ret_val = phy->ops.write_reg(hw, 0x2F5B,
+ phy_saved_data);
if (ret_val)
goto out;
@@ -838,21 +828,18 @@ static s32 e1000_config_dsp_after_link_change_82541(struct e1000_hw *hw,
msec_delay_irq(20);
- ret_val = phy->ops.write_reg(hw,
- 0x0000,
- IGP01E1000_IEEE_FORCE_GIG);
+ ret_val = phy->ops.write_reg(hw, 0x0000,
+ IGP01E1000_IEEE_FORCE_GIG);
if (ret_val)
goto out;
- ret_val = phy->ops.write_reg(hw,
- IGP01E1000_PHY_DSP_FFE,
- IGP01E1000_PHY_DSP_FFE_DEFAULT);
+ ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_DSP_FFE,
+ IGP01E1000_PHY_DSP_FFE_DEFAULT);
if (ret_val)
goto out;
- ret_val = phy->ops.write_reg(hw,
- 0x0000,
- IGP01E1000_IEEE_RESTART_AUTONEG);
+ ret_val = phy->ops.write_reg(hw, 0x0000,
+ IGP01E1000_IEEE_RESTART_AUTONEG);
if (ret_val)
goto out;
@@ -889,11 +876,10 @@ static s32 e1000_get_cable_length_igp_82541(struct e1000_hw *hw)
u16 i, data;
u16 cur_agc_value, agc_value = 0;
u16 min_agc_value = IGP01E1000_AGC_LENGTH_TABLE_SIZE;
- u16 agc_reg_array[IGP01E1000_PHY_CHANNEL_NUM] =
- {IGP01E1000_PHY_AGC_A,
- IGP01E1000_PHY_AGC_B,
- IGP01E1000_PHY_AGC_C,
- IGP01E1000_PHY_AGC_D};
+ u16 agc_reg_array[IGP01E1000_PHY_CHANNEL_NUM] = {IGP01E1000_PHY_AGC_A,
+ IGP01E1000_PHY_AGC_B,
+ IGP01E1000_PHY_AGC_C,
+ IGP01E1000_PHY_AGC_D};
DEBUGFUNC("e1000_get_cable_length_igp_82541");
@@ -929,12 +915,12 @@ static s32 e1000_get_cable_length_igp_82541(struct e1000_hw *hw)
}
phy->min_cable_length = (e1000_igp_cable_length_table[agc_value] >
- IGP01E1000_AGC_RANGE)
- ? (e1000_igp_cable_length_table[agc_value] -
- IGP01E1000_AGC_RANGE)
- : 0;
+ IGP01E1000_AGC_RANGE)
+ ? (e1000_igp_cable_length_table[agc_value] -
+ IGP01E1000_AGC_RANGE)
+ : 0;
phy->max_cable_length = e1000_igp_cable_length_table[agc_value] +
- IGP01E1000_AGC_RANGE;
+ IGP01E1000_AGC_RANGE;
phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2;
@@ -992,50 +978,48 @@ static s32 e1000_set_d3_lplu_state_82541(struct e1000_hw *hw, bool active)
*/
if (phy->smart_speed == e1000_smart_speed_on) {
ret_val = phy->ops.read_reg(hw,
- IGP01E1000_PHY_PORT_CONFIG,
- &data);
+ IGP01E1000_PHY_PORT_CONFIG,
+ &data);
if (ret_val)
goto out;
data |= IGP01E1000_PSCFR_SMART_SPEED;
ret_val = phy->ops.write_reg(hw,
- IGP01E1000_PHY_PORT_CONFIG,
- data);
+ IGP01E1000_PHY_PORT_CONFIG,
+ data);
if (ret_val)
goto out;
} else if (phy->smart_speed == e1000_smart_speed_off) {
ret_val = phy->ops.read_reg(hw,
- IGP01E1000_PHY_PORT_CONFIG,
- &data);
+ IGP01E1000_PHY_PORT_CONFIG,
+ &data);
if (ret_val)
goto out;
data &= ~IGP01E1000_PSCFR_SMART_SPEED;
ret_val = phy->ops.write_reg(hw,
- IGP01E1000_PHY_PORT_CONFIG,
- data);
+ IGP01E1000_PHY_PORT_CONFIG,
+ data);
if (ret_val)
goto out;
}
} else if ((phy->autoneg_advertised == E1000_ALL_SPEED_DUPLEX) ||
- (phy->autoneg_advertised == E1000_ALL_NOT_GIG) ||
- (phy->autoneg_advertised == E1000_ALL_10_SPEED)) {
+ (phy->autoneg_advertised == E1000_ALL_NOT_GIG) ||
+ (phy->autoneg_advertised == E1000_ALL_10_SPEED)) {
data |= IGP01E1000_GMII_FLEX_SPD;
ret_val = phy->ops.write_reg(hw, IGP01E1000_GMII_FIFO, data);
if (ret_val)
goto out;
/* When LPLU is enabled, we should disable SmartSpeed */
- ret_val = phy->ops.read_reg(hw,
- IGP01E1000_PHY_PORT_CONFIG,
- &data);
+ ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
+ &data);
if (ret_val)
goto out;
data &= ~IGP01E1000_PSCFR_SMART_SPEED;
- ret_val = phy->ops.write_reg(hw,
- IGP01E1000_PHY_PORT_CONFIG,
- data);
+ ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
+ data);
}
out:
@@ -1056,16 +1040,14 @@ static s32 e1000_setup_led_82541(struct e1000_hw *hw)
DEBUGFUNC("e1000_setup_led_82541");
- ret_val = hw->phy.ops.read_reg(hw,
- IGP01E1000_GMII_FIFO,
- &dev_spec->spd_default);
+ ret_val = hw->phy.ops.read_reg(hw, IGP01E1000_GMII_FIFO,
+ &dev_spec->spd_default);
if (ret_val)
goto out;
- ret_val = hw->phy.ops.write_reg(hw,
- IGP01E1000_GMII_FIFO,
- (u16)(dev_spec->spd_default &
- ~IGP01E1000_GMII_SPD));
+ ret_val = hw->phy.ops.write_reg(hw, IGP01E1000_GMII_FIFO,
+ (u16)(dev_spec->spd_default &
+ ~IGP01E1000_GMII_SPD));
if (ret_val)
goto out;
@@ -1089,9 +1071,8 @@ static s32 e1000_cleanup_led_82541(struct e1000_hw *hw)
DEBUGFUNC("e1000_cleanup_led_82541");
- ret_val = hw->phy.ops.write_reg(hw,
- IGP01E1000_GMII_FIFO,
- dev_spec->spd_default);
+ ret_val = hw->phy.ops.write_reg(hw, IGP01E1000_GMII_FIFO,
+ dev_spec->spd_default);
if (ret_val)
goto out;
@@ -1178,14 +1159,12 @@ static s32 e1000_phy_init_script_82541(struct e1000_hw *hw)
u16 fused, fine, coarse;
/* Move to analog registers page */
- hw->phy.ops.read_reg(hw,
- IGP01E1000_ANALOG_SPARE_FUSE_STATUS,
- &fused);
+ hw->phy.ops.read_reg(hw, IGP01E1000_ANALOG_SPARE_FUSE_STATUS,
+ &fused);
if (!(fused & IGP01E1000_ANALOG_SPARE_FUSE_ENABLED)) {
- hw->phy.ops.read_reg(hw,
- IGP01E1000_ANALOG_FUSE_STATUS,
- &fused);
+ hw->phy.ops.read_reg(hw, IGP01E1000_ANALOG_FUSE_STATUS,
+ &fused);
fine = fused & IGP01E1000_ANALOG_FUSE_FINE_MASK;
coarse = fused & IGP01E1000_ANALOG_FUSE_COARSE_MASK;
@@ -1194,19 +1173,19 @@ static s32 e1000_phy_init_script_82541(struct e1000_hw *hw)
coarse -= IGP01E1000_ANALOG_FUSE_COARSE_10;
fine -= IGP01E1000_ANALOG_FUSE_FINE_1;
} else if (coarse ==
- IGP01E1000_ANALOG_FUSE_COARSE_THRESH)
+ IGP01E1000_ANALOG_FUSE_COARSE_THRESH)
fine -= IGP01E1000_ANALOG_FUSE_FINE_10;
fused = (fused & IGP01E1000_ANALOG_FUSE_POLY_MASK) |
- (fine & IGP01E1000_ANALOG_FUSE_FINE_MASK) |
- (coarse & IGP01E1000_ANALOG_FUSE_COARSE_MASK);
+ (fine & IGP01E1000_ANALOG_FUSE_FINE_MASK) |
+ (coarse & IGP01E1000_ANALOG_FUSE_COARSE_MASK);
hw->phy.ops.write_reg(hw,
- IGP01E1000_ANALOG_FUSE_CONTROL,
- fused);
+ IGP01E1000_ANALOG_FUSE_CONTROL,
+ fused);
hw->phy.ops.write_reg(hw,
- IGP01E1000_ANALOG_FUSE_BYPASS,
- IGP01E1000_ANALOG_FUSE_ENABLE_SW_CONTROL);
+ IGP01E1000_ANALOG_FUSE_BYPASS,
+ IGP01E1000_ANALOG_FUSE_ENABLE_SW_CONTROL);
}
}
diff --git a/usr/src/uts/common/io/e1000api/e1000_82541.h b/usr/src/uts/common/io/e1000api/e1000_82541.h
index 717f7959ba..7a01fd43ad 100644
--- a/usr/src/uts/common/io/e1000api/e1000_82541.h
+++ b/usr/src/uts/common/io/e1000api/e1000_82541.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2008, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -35,82 +35,58 @@
#ifndef _E1000_82541_H_
#define _E1000_82541_H_
-#ifdef __cplusplus
-extern "C" {
-#endif
-
#define NVM_WORD_SIZE_BASE_SHIFT_82541 (NVM_WORD_SIZE_BASE_SHIFT + 1)
-#define IGP01E1000_PHY_CHANNEL_NUM 4
+#define IGP01E1000_PHY_CHANNEL_NUM 4
-#define IGP01E1000_PHY_AGC_A 0x1172
-#define IGP01E1000_PHY_AGC_B 0x1272
-#define IGP01E1000_PHY_AGC_C 0x1472
-#define IGP01E1000_PHY_AGC_D 0x1872
+#define IGP01E1000_PHY_AGC_A 0x1172
+#define IGP01E1000_PHY_AGC_B 0x1272
+#define IGP01E1000_PHY_AGC_C 0x1472
+#define IGP01E1000_PHY_AGC_D 0x1872
-#define IGP01E1000_PHY_AGC_PARAM_A 0x1171
-#define IGP01E1000_PHY_AGC_PARAM_B 0x1271
-#define IGP01E1000_PHY_AGC_PARAM_C 0x1471
-#define IGP01E1000_PHY_AGC_PARAM_D 0x1871
+#define IGP01E1000_PHY_AGC_PARAM_A 0x1171
+#define IGP01E1000_PHY_AGC_PARAM_B 0x1271
+#define IGP01E1000_PHY_AGC_PARAM_C 0x1471
+#define IGP01E1000_PHY_AGC_PARAM_D 0x1871
-#define IGP01E1000_PHY_EDAC_MU_INDEX 0xC000
-#define IGP01E1000_PHY_EDAC_SIGN_EXT_9_BITS 0x8000
+#define IGP01E1000_PHY_EDAC_MU_INDEX 0xC000
+#define IGP01E1000_PHY_EDAC_SIGN_EXT_9_BITS 0x8000
-#define IGP01E1000_PHY_DSP_RESET 0x1F33
+#define IGP01E1000_PHY_DSP_RESET 0x1F33
-#define IGP01E1000_PHY_DSP_FFE 0x1F35
-#define IGP01E1000_PHY_DSP_FFE_CM_CP 0x0069
-#define IGP01E1000_PHY_DSP_FFE_DEFAULT 0x002A
+#define IGP01E1000_PHY_DSP_FFE 0x1F35
+#define IGP01E1000_PHY_DSP_FFE_CM_CP 0x0069
+#define IGP01E1000_PHY_DSP_FFE_DEFAULT 0x002A
-#define IGP01E1000_IEEE_FORCE_GIG 0x0140
-#define IGP01E1000_IEEE_RESTART_AUTONEG 0x3300
+#define IGP01E1000_IEEE_FORCE_GIG 0x0140
+#define IGP01E1000_IEEE_RESTART_AUTONEG 0x3300
-#define IGP01E1000_AGC_LENGTH_SHIFT 7
-#define IGP01E1000_AGC_RANGE 10
+#define IGP01E1000_AGC_LENGTH_SHIFT 7
+#define IGP01E1000_AGC_RANGE 10
-#define FFE_IDLE_ERR_COUNT_TIMEOUT_20 20
-#define FFE_IDLE_ERR_COUNT_TIMEOUT_100 100
+#define FFE_IDLE_ERR_COUNT_TIMEOUT_20 20
+#define FFE_IDLE_ERR_COUNT_TIMEOUT_100 100
-#define IGP01E1000_ANALOG_FUSE_STATUS 0x20D0
-#define IGP01E1000_ANALOG_SPARE_FUSE_STATUS 0x20D1
-#define IGP01E1000_ANALOG_FUSE_CONTROL 0x20DC
-#define IGP01E1000_ANALOG_FUSE_BYPASS 0x20DE
+#define IGP01E1000_ANALOG_FUSE_STATUS 0x20D0
+#define IGP01E1000_ANALOG_SPARE_FUSE_STATUS 0x20D1
+#define IGP01E1000_ANALOG_FUSE_CONTROL 0x20DC
+#define IGP01E1000_ANALOG_FUSE_BYPASS 0x20DE
-#define IGP01E1000_ANALOG_SPARE_FUSE_ENABLED 0x0100
-#define IGP01E1000_ANALOG_FUSE_FINE_MASK 0x0F80
-#define IGP01E1000_ANALOG_FUSE_COARSE_MASK 0x0070
-#define IGP01E1000_ANALOG_FUSE_COARSE_THRESH 0x0040
-#define IGP01E1000_ANALOG_FUSE_COARSE_10 0x0010
-#define IGP01E1000_ANALOG_FUSE_FINE_1 0x0080
-#define IGP01E1000_ANALOG_FUSE_FINE_10 0x0500
-#define IGP01E1000_ANALOG_FUSE_POLY_MASK 0xF000
+#define IGP01E1000_ANALOG_SPARE_FUSE_ENABLED 0x0100
+#define IGP01E1000_ANALOG_FUSE_FINE_MASK 0x0F80
+#define IGP01E1000_ANALOG_FUSE_COARSE_MASK 0x0070
+#define IGP01E1000_ANALOG_FUSE_COARSE_THRESH 0x0040
+#define IGP01E1000_ANALOG_FUSE_COARSE_10 0x0010
+#define IGP01E1000_ANALOG_FUSE_FINE_1 0x0080
+#define IGP01E1000_ANALOG_FUSE_FINE_10 0x0500
+#define IGP01E1000_ANALOG_FUSE_POLY_MASK 0xF000
#define IGP01E1000_ANALOG_FUSE_ENABLE_SW_CONTROL 0x0002
-#define IGP01E1000_MSE_CHANNEL_D 0x000F
-#define IGP01E1000_MSE_CHANNEL_C 0x00F0
-#define IGP01E1000_MSE_CHANNEL_B 0x0F00
-#define IGP01E1000_MSE_CHANNEL_A 0xF000
-
-#define E1000_FIFO_MULTIPLIER 0x80
-#define E1000_FIFO_HDR_SIZE 0x10
-#define E1000_FIFO_GRANULARITY 0x10
-#define E1000_FIFO_PAD_82547 0x3E0
-#define E1000_ERR_FIFO_WRAP 8
-
-#define DSP_RESET_ENABLE 0x0
-#define DSP_RESET_DISABLE 0x2
-#define E1000_MAX_DSP_RESETS 10
+#define IGP01E1000_MSE_CHANNEL_D 0x000F
+#define IGP01E1000_MSE_CHANNEL_C 0x00F0
+#define IGP01E1000_MSE_CHANNEL_B 0x0F00
+#define IGP01E1000_MSE_CHANNEL_A 0xF000
-#define E1000_ROUNDUP(size, unit) (((size) + (unit) - 1) & ~((unit) - 1))
void e1000_init_script_state_82541(struct e1000_hw *hw, bool state);
-s32 e1000_fifo_workaround_82547(struct e1000_hw *hw, u16 length);
-void e1000_update_tx_fifo_head_82547(struct e1000_hw *hw, u32 length);
-void e1000_set_ttl_workaround_state_82541(struct e1000_hw *hw, bool state);
-bool e1000_ttl_workaround_enabled_82541(struct e1000_hw *hw);
-s32 e1000_igp_ttl_workaround_82547(struct e1000_hw *hw);
-
-#ifdef __cplusplus
-}
#endif
-#endif /* _E1000_82541_H_ */
diff --git a/usr/src/uts/common/io/e1000api/e1000_82542.c b/usr/src/uts/common/io/e1000api/e1000_82542.c
index 19d5402831..4cca9b2b2c 100644
--- a/usr/src/uts/common/io/e1000api/e1000_82542.c
+++ b/usr/src/uts/common/io/e1000api/e1000_82542.c
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2014, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -62,7 +62,7 @@ static s32 e1000_init_phy_params_82542(struct e1000_hw *hw)
DEBUGFUNC("e1000_init_phy_params_82542");
- phy->type = e1000_phy_none;
+ phy->type = e1000_phy_none;
return ret_val;
}
@@ -77,18 +77,18 @@ static s32 e1000_init_nvm_params_82542(struct e1000_hw *hw)
DEBUGFUNC("e1000_init_nvm_params_82542");
- nvm->address_bits = 6;
- nvm->delay_usec = 50;
- nvm->opcode_bits = 3;
- nvm->type = e1000_nvm_eeprom_microwire;
- nvm->word_size = 64;
+ nvm->address_bits = 6;
+ nvm->delay_usec = 50;
+ nvm->opcode_bits = 3;
+ nvm->type = e1000_nvm_eeprom_microwire;
+ nvm->word_size = 64;
/* Function Pointers */
- nvm->ops.read = e1000_read_nvm_microwire;
- nvm->ops.release = e1000_stop_nvm;
- nvm->ops.write = e1000_write_nvm_microwire;
- nvm->ops.update = e1000_update_nvm_checksum_generic;
- nvm->ops.validate = e1000_validate_nvm_checksum_generic;
+ nvm->ops.read = e1000_read_nvm_microwire;
+ nvm->ops.release = e1000_stop_nvm;
+ nvm->ops.write = e1000_write_nvm_microwire;
+ nvm->ops.update = e1000_update_nvm_checksum_generic;
+ nvm->ops.validate = e1000_validate_nvm_checksum_generic;
return E1000_SUCCESS;
}
@@ -124,7 +124,8 @@ static s32 e1000_init_mac_params_82542(struct e1000_hw *hw)
/* link setup */
mac->ops.setup_link = e1000_setup_link_82542;
/* phy/fiber/serdes setup */
- mac->ops.setup_physical_interface = e1000_setup_fiber_serdes_link_generic;
+ mac->ops.setup_physical_interface =
+ e1000_setup_fiber_serdes_link_generic;
/* check for link */
mac->ops.check_for_link = e1000_check_for_fiber_link_generic;
/* multicast address update */
@@ -143,7 +144,8 @@ static s32 e1000_init_mac_params_82542(struct e1000_hw *hw)
/* clear hardware counters */
mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_82542;
/* link info */
- mac->ops.get_link_up_info = e1000_get_speed_and_duplex_fiber_serdes_generic;
+ mac->ops.get_link_up_info =
+ e1000_get_speed_and_duplex_fiber_serdes_generic;
return E1000_SUCCESS;
}
@@ -315,7 +317,7 @@ static s32 e1000_init_hw_82542(struct e1000_hw *hw)
static s32 e1000_setup_link_82542(struct e1000_hw *hw)
{
struct e1000_mac_info *mac = &hw->mac;
- s32 ret_val = E1000_SUCCESS;
+ s32 ret_val;
DEBUGFUNC("e1000_setup_link_82542");
@@ -325,7 +327,7 @@ static s32 e1000_setup_link_82542(struct e1000_hw *hw)
hw->fc.requested_mode &= ~e1000_fc_tx_pause;
- if (mac->report_tx_early == 1)
+ if (mac->report_tx_early)
hw->fc.requested_mode &= ~e1000_fc_rx_pause;
/*
@@ -335,7 +337,7 @@ static s32 e1000_setup_link_82542(struct e1000_hw *hw)
hw->fc.current_mode = hw->fc.requested_mode;
DEBUGOUT1("After fix-ups FlowControl is now = %x\n",
- hw->fc.current_mode);
+ hw->fc.current_mode);
/* Call the necessary subroutine to configure the link. */
ret_val = mac->ops.setup_physical_interface(hw);
@@ -419,9 +421,8 @@ static int e1000_rar_set_82542(struct e1000_hw *hw, u8 *addr, u32 index)
* HW expects these in little endian so we reverse the byte order
* from network order (big endian) to little endian
*/
- rar_low = ((u32) addr[0] |
- ((u32) addr[1] << 8) |
- ((u32) addr[2] << 16) | ((u32) addr[3] << 24));
+ rar_low = ((u32) addr[0] | ((u32) addr[1] << 8) |
+ ((u32) addr[2] << 16) | ((u32) addr[3] << 24));
rar_high = ((u32) addr[4] | ((u32) addr[5] << 8));
@@ -431,6 +432,7 @@ static int e1000_rar_set_82542(struct e1000_hw *hw, u8 *addr, u32 index)
E1000_WRITE_REG_ARRAY(hw, E1000_RA, (index << 1), rar_low);
E1000_WRITE_REG_ARRAY(hw, E1000_RA, ((index << 1) + 1), rar_high);
+
return E1000_SUCCESS;
}
@@ -563,7 +565,7 @@ static void e1000_clear_hw_cntrs_82542(struct e1000_hw *hw)
*
* Reads the device MAC address from the EEPROM and stores the value.
**/
-static s32 e1000_read_mac_addr_82542(struct e1000_hw *hw)
+s32 e1000_read_mac_addr_82542(struct e1000_hw *hw)
{
s32 ret_val = E1000_SUCCESS;
u16 offset, nvm_data, i;
diff --git a/usr/src/uts/common/io/e1000api/e1000_82543.c b/usr/src/uts/common/io/e1000api/e1000_82543.c
index 1c01658cfc..474387d2cb 100644
--- a/usr/src/uts/common/io/e1000api/e1000_82543.c
+++ b/usr/src/uts/common/io/e1000api/e1000_82543.c
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2011, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -47,9 +47,9 @@ static s32 e1000_init_phy_params_82543(struct e1000_hw *hw);
static s32 e1000_init_nvm_params_82543(struct e1000_hw *hw);
static s32 e1000_init_mac_params_82543(struct e1000_hw *hw);
static s32 e1000_read_phy_reg_82543(struct e1000_hw *hw, u32 offset,
- u16 *data);
+ u16 *data);
static s32 e1000_write_phy_reg_82543(struct e1000_hw *hw, u32 offset,
- u16 data);
+ u16 data);
static s32 e1000_phy_force_speed_duplex_82543(struct e1000_hw *hw);
static s32 e1000_phy_hw_reset_82543(struct e1000_hw *hw);
static s32 e1000_reset_hw_82543(struct e1000_hw *hw);
@@ -62,7 +62,7 @@ static s32 e1000_check_for_fiber_link_82543(struct e1000_hw *hw);
static s32 e1000_led_on_82543(struct e1000_hw *hw);
static s32 e1000_led_off_82543(struct e1000_hw *hw);
static void e1000_write_vfta_82543(struct e1000_hw *hw, u32 offset,
- u32 value);
+ u32 value);
static void e1000_clear_hw_cntrs_82543(struct e1000_hw *hw);
static s32 e1000_config_mac_to_phy_82543(struct e1000_hw *hw);
static bool e1000_init_phy_disabled_82543(struct e1000_hw *hw);
@@ -71,7 +71,7 @@ static s32 e1000_polarity_reversal_workaround_82543(struct e1000_hw *hw);
static void e1000_raise_mdi_clk_82543(struct e1000_hw *hw, u32 *ctrl);
static u16 e1000_shift_in_mdi_bits_82543(struct e1000_hw *hw);
static void e1000_shift_out_mdi_bits_82543(struct e1000_hw *hw, u32 data,
- u16 count);
+ u16 count);
static bool e1000_tbi_compatibility_enabled_82543(struct e1000_hw *hw);
static void e1000_set_tbi_sbp_82543(struct e1000_hw *hw, bool state);
static s32 e1000_read_mac_addr_82543(struct e1000_hw *hw);
@@ -89,34 +89,34 @@ static s32 e1000_init_phy_params_82543(struct e1000_hw *hw)
DEBUGFUNC("e1000_init_phy_params_82543");
if (hw->phy.media_type != e1000_media_type_copper) {
- phy->type = e1000_phy_none;
+ phy->type = e1000_phy_none;
goto out;
} else {
- phy->ops.power_up = e1000_power_up_phy_copper;
- phy->ops.power_down = e1000_power_down_phy_copper;
+ phy->ops.power_up = e1000_power_up_phy_copper;
+ phy->ops.power_down = e1000_power_down_phy_copper;
}
- phy->addr = 1;
- phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT;
- phy->reset_delay_us = 10000;
- phy->type = e1000_phy_m88;
+ phy->addr = 1;
+ phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT;
+ phy->reset_delay_us = 10000;
+ phy->type = e1000_phy_m88;
/* Function Pointers */
- phy->ops.check_polarity = e1000_check_polarity_m88;
- phy->ops.commit = e1000_phy_sw_reset_generic;
- phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_82543;
- phy->ops.get_cable_length = e1000_get_cable_length_m88;
- phy->ops.get_cfg_done = e1000_get_cfg_done_generic;
- phy->ops.read_reg = (hw->mac.type == e1000_82543)
- ? e1000_read_phy_reg_82543
- : e1000_read_phy_reg_m88;
- phy->ops.reset = (hw->mac.type == e1000_82543)
- ? e1000_phy_hw_reset_82543
- : e1000_phy_hw_reset_generic;
- phy->ops.write_reg = (hw->mac.type == e1000_82543)
- ? e1000_write_phy_reg_82543
- : e1000_write_phy_reg_m88;
- phy->ops.get_info = e1000_get_phy_info_m88;
+ phy->ops.check_polarity = e1000_check_polarity_m88;
+ phy->ops.commit = e1000_phy_sw_reset_generic;
+ phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_82543;
+ phy->ops.get_cable_length = e1000_get_cable_length_m88;
+ phy->ops.get_cfg_done = e1000_get_cfg_done_generic;
+ phy->ops.read_reg = (hw->mac.type == e1000_82543)
+ ? e1000_read_phy_reg_82543
+ : e1000_read_phy_reg_m88;
+ phy->ops.reset = (hw->mac.type == e1000_82543)
+ ? e1000_phy_hw_reset_82543
+ : e1000_phy_hw_reset_generic;
+ phy->ops.write_reg = (hw->mac.type == e1000_82543)
+ ? e1000_write_phy_reg_82543
+ : e1000_write_phy_reg_m88;
+ phy->ops.get_info = e1000_get_phy_info_m88;
/*
* The external PHY of the 82543 can be in a funky state.
@@ -170,18 +170,18 @@ static s32 e1000_init_nvm_params_82543(struct e1000_hw *hw)
DEBUGFUNC("e1000_init_nvm_params_82543");
- nvm->type = e1000_nvm_eeprom_microwire;
- nvm->word_size = 64;
- nvm->delay_usec = 50;
- nvm->address_bits = 6;
- nvm->opcode_bits = 3;
+ nvm->type = e1000_nvm_eeprom_microwire;
+ nvm->word_size = 64;
+ nvm->delay_usec = 50;
+ nvm->address_bits = 6;
+ nvm->opcode_bits = 3;
/* Function Pointers */
- nvm->ops.read = e1000_read_nvm_microwire;
- nvm->ops.update = e1000_update_nvm_checksum_generic;
+ nvm->ops.read = e1000_read_nvm_microwire;
+ nvm->ops.update = e1000_update_nvm_checksum_generic;
nvm->ops.valid_led_default = e1000_valid_led_default_generic;
- nvm->ops.validate = e1000_validate_nvm_checksum_generic;
- nvm->ops.write = e1000_write_nvm_microwire;
+ nvm->ops.validate = e1000_validate_nvm_checksum_generic;
+ nvm->ops.write = e1000_write_nvm_microwire;
return E1000_SUCCESS;
}
@@ -226,19 +226,18 @@ static s32 e1000_init_mac_params_82543(struct e1000_hw *hw)
mac->ops.setup_link = e1000_setup_link_82543;
/* physical interface setup */
mac->ops.setup_physical_interface =
- (hw->phy.media_type == e1000_media_type_copper)
- ? e1000_setup_copper_link_82543
- : e1000_setup_fiber_link_82543;
+ (hw->phy.media_type == e1000_media_type_copper)
+ ? e1000_setup_copper_link_82543 : e1000_setup_fiber_link_82543;
/* check for link */
mac->ops.check_for_link =
- (hw->phy.media_type == e1000_media_type_copper)
- ? e1000_check_for_copper_link_82543
- : e1000_check_for_fiber_link_82543;
+ (hw->phy.media_type == e1000_media_type_copper)
+ ? e1000_check_for_copper_link_82543
+ : e1000_check_for_fiber_link_82543;
/* link info */
mac->ops.get_link_up_info =
- (hw->phy.media_type == e1000_media_type_copper)
- ? e1000_get_speed_and_duplex_copper_generic
- : e1000_get_speed_and_duplex_fiber_serdes_generic;
+ (hw->phy.media_type == e1000_media_type_copper)
+ ? e1000_get_speed_and_duplex_copper_generic
+ : e1000_get_speed_and_duplex_fiber_serdes_generic;
/* multicast address update */
mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic;
/* writing VFTA */
@@ -295,8 +294,7 @@ static bool e1000_tbi_compatibility_enabled_82543(struct e1000_hw *hw)
goto out;
}
- state = (dev_spec->tbi_compatibility & TBI_COMPAT_ENABLED)
- ? TRUE : FALSE;
+ state = !!(dev_spec->tbi_compatibility & TBI_COMPAT_ENABLED);
out:
return state;
@@ -348,8 +346,7 @@ bool e1000_tbi_sbp_enabled_82543(struct e1000_hw *hw)
goto out;
}
- state = (dev_spec->tbi_compatibility & TBI_SBP_ENABLED)
- ? TRUE : FALSE;
+ state = !!(dev_spec->tbi_compatibility & TBI_SBP_ENABLED);
out:
return state;
@@ -412,8 +409,8 @@ out:
* Adjusts the statistic counters when a frame is accepted by TBI_ACCEPT
**/
void e1000_tbi_adjust_stats_82543(struct e1000_hw *hw,
- struct e1000_hw_stats *stats, u32 frame_len,
- u8 *mac_addr, u32 max_frame_size)
+ struct e1000_hw_stats *stats, u32 frame_len,
+ u8 *mac_addr, u32 max_frame_size)
{
if (!(e1000_tbi_sbp_enabled_82543(hw)))
goto out;
@@ -425,12 +422,12 @@ void e1000_tbi_adjust_stats_82543(struct e1000_hw *hw,
* counters overcount this packet as a CRC error and undercount
* the packet as a good packet
*/
- /* This packet should not be counted as a CRC error. */
+ /* This packet should not be counted as a CRC error. */
stats->crcerrs--;
- /* This packet does count as a Good Packet Received. */
+ /* This packet does count as a Good Packet Received. */
stats->gprc++;
- /* Adjust the Good Octets received counters */
+ /* Adjust the Good Octets received counters */
stats->gorc += frame_len;
/*
@@ -446,7 +443,7 @@ void e1000_tbi_adjust_stats_82543(struct e1000_hw *hw,
stats->mprc++;
/*
- * In this case, the hardware has overcounted the number of
+ * In this case, the hardware has over counted the number of
* oversize frames.
*/
if ((frame_len == max_frame_size) && (stats->roc > 0))
@@ -513,7 +510,7 @@ static s32 e1000_read_phy_reg_82543(struct e1000_hw *hw, u32 offset, u16 *data)
* e1000_shift_out_mdi_bits routine five different times. The format
* of an MII read instruction consists of a shift out of 14 bits and
* is defined as follows:
- * <Preamble><SOF><Op Code><Phy Addr><Offset>
+ * <Preamble><SOF><Op Code><Phy Addr><Offset>
* followed by a shift in of 18 bits. This first two bits shifted in
* are TurnAround bits used to avoid contention on the MDIO pin when a
* READ operation is performed. These two bits are thrown away
@@ -572,9 +569,9 @@ static s32 e1000_write_phy_reg_82543(struct e1000_hw *hw, u32 offset, u16 data)
* <Preamble><SOF><Op Code><Phy Addr><Reg Addr><Turnaround><Data>.
*/
mdic = ((PHY_TURNAROUND) | (offset << 2) | (hw->phy.addr << 7) |
- (PHY_OP_WRITE << 12) | (PHY_SOF << 14));
+ (PHY_OP_WRITE << 12) | (PHY_SOF << 14));
mdic <<= 16;
- mdic |= (u32) data;
+ mdic |= (u32)data;
e1000_shift_out_mdi_bits_82543(hw, mdic, 32);
@@ -631,7 +628,7 @@ static void e1000_lower_mdi_clk_82543(struct e1000_hw *hw, u32 *ctrl)
* In order to do this, "data" must be broken down into bits.
**/
static void e1000_shift_out_mdi_bits_82543(struct e1000_hw *hw, u32 data,
- u16 count)
+ u16 count)
{
u32 ctrl, mask;
@@ -642,7 +639,7 @@ static void e1000_shift_out_mdi_bits_82543(struct e1000_hw *hw, u32 data,
* into bits.
*/
mask = 0x01;
- mask <<= (count -1);
+ mask <<= (count - 1);
ctrl = E1000_READ_REG(hw, E1000_CTRL);
@@ -656,8 +653,10 @@ static void e1000_shift_out_mdi_bits_82543(struct e1000_hw *hw, u32 data,
* A "0" is shifted out to the PHY by setting the MDIO bit to
* "0" and then raising and lowering the clock.
*/
- if (data & mask) ctrl |= E1000_CTRL_MDIO;
- else ctrl &= ~E1000_CTRL_MDIO;
+ if (data & mask)
+ ctrl |= E1000_CTRL_MDIO;
+ else
+ ctrl &= ~E1000_CTRL_MDIO;
E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
E1000_WRITE_FLUSH(hw);
@@ -749,8 +748,8 @@ static s32 e1000_phy_force_speed_duplex_82543(struct e1000_hw *hw)
if (ret_val)
goto out;
- if (!hw->mac.autoneg &&
- (hw->mac.forced_speed_duplex & E1000_ALL_10_SPEED))
+ if (!hw->mac.autoneg && (hw->mac.forced_speed_duplex &
+ E1000_ALL_10_SPEED))
ret_val = e1000_polarity_reversal_workaround_82543(hw);
out:
@@ -808,7 +807,7 @@ static s32 e1000_polarity_reversal_workaround_82543(struct e1000_hw *hw)
if (ret_val)
goto out;
- if ((mii_status_reg & ~MII_SR_LINK_STATUS) == 0)
+ if (!(mii_status_reg & ~MII_SR_LINK_STATUS))
break;
msec_delay_irq(100);
}
@@ -901,7 +900,7 @@ static s32 e1000_phy_hw_reset_82543(struct e1000_hw *hw)
**/
static s32 e1000_reset_hw_82543(struct e1000_hw *hw)
{
- u32 ctrl, icr;
+ u32 ctrl;
s32 ret_val = E1000_SUCCESS;
DEBUGFUNC("e1000_reset_hw_82543");
@@ -943,7 +942,7 @@ static s32 e1000_reset_hw_82543(struct e1000_hw *hw)
/* Masking off and clearing any pending interrupts */
E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
- icr = E1000_READ_REG(hw, E1000_ICR);
+ E1000_READ_REG(hw, E1000_ICR);
return ret_val;
}
@@ -1040,7 +1039,7 @@ static s32 e1000_setup_link_82543(struct e1000_hw *hw)
goto out;
}
ctrl_ext = ((data & NVM_WORD0F_SWPDIO_EXT_MASK) <<
- NVM_SWDPIO_EXT_SHIFT);
+ NVM_SWDPIO_EXT_SHIFT);
E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
}
@@ -1114,10 +1113,8 @@ static s32 e1000_setup_copper_link_82543(struct e1000_hw *hw)
* Check link status. Wait up to 100 microseconds for link to become
* valid.
*/
- ret_val = e1000_phy_has_link_generic(hw,
- COPPER_LINK_UP_LIMIT,
- 10,
- &link);
+ ret_val = e1000_phy_has_link_generic(hw, COPPER_LINK_UP_LIMIT, 10,
+ &link);
if (ret_val)
goto out;
@@ -1177,11 +1174,10 @@ static s32 e1000_setup_fiber_link_82543(struct e1000_hw *hw)
* optics detect a signal. If we have a signal, then poll for a
* "Link-Up" indication.
*/
- if (!(E1000_READ_REG(hw, E1000_CTRL) & E1000_CTRL_SWDPIN1)) {
+ if (!(E1000_READ_REG(hw, E1000_CTRL) & E1000_CTRL_SWDPIN1))
ret_val = e1000_poll_fiber_serdes_link_generic(hw);
- } else {
+ else
DEBUGOUT("No signal detected\n");
- }
out:
return ret_val;
@@ -1275,9 +1271,8 @@ static s32 e1000_check_for_copper_link_82543(struct e1000_hw *hw)
* different link partner.
*/
ret_val = e1000_config_fc_after_link_up_generic(hw);
- if (ret_val) {
+ if (ret_val)
DEBUGOUT("Error configuring flow control\n");
- }
/*
* At this point we know that we are on copper and we have
@@ -1359,8 +1354,8 @@ static s32 e1000_check_for_fiber_link_82543(struct e1000_hw *hw)
if ((!(ctrl & E1000_CTRL_SWDPIN1)) &&
(!(status & E1000_STATUS_LU)) &&
(!(rxcw & E1000_RXCW_C))) {
- if (mac->autoneg_failed == 0) {
- mac->autoneg_failed = 1;
+ if (!mac->autoneg_failed) {
+ mac->autoneg_failed = TRUE;
ret_val = 0;
goto out;
}
diff --git a/usr/src/uts/common/io/e1000api/e1000_82543.h b/usr/src/uts/common/io/e1000api/e1000_82543.h
index 60e5c15dda..e8edda5d2b 100644
--- a/usr/src/uts/common/io/e1000api/e1000_82543.h
+++ b/usr/src/uts/common/io/e1000api/e1000_82543.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2008, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -35,23 +35,23 @@
#ifndef _E1000_82543_H_
#define _E1000_82543_H_
-#define PHY_PREAMBLE 0xFFFFFFFF
-#define PHY_PREAMBLE_SIZE 32
-#define PHY_SOF 0x1
-#define PHY_OP_READ 0x2
-#define PHY_OP_WRITE 0x1
-#define PHY_TURNAROUND 0x2
+#define PHY_PREAMBLE 0xFFFFFFFF
+#define PHY_PREAMBLE_SIZE 32
+#define PHY_SOF 0x1
+#define PHY_OP_READ 0x2
+#define PHY_OP_WRITE 0x1
+#define PHY_TURNAROUND 0x2
-#define TBI_COMPAT_ENABLED 0x1 /* Global "knob" for the workaround */
+#define TBI_COMPAT_ENABLED 0x1 /* Global "knob" for the workaround */
/* If TBI_COMPAT_ENABLED, then this is the current state (on/off) */
-#define TBI_SBP_ENABLED 0x2
-
+#define TBI_SBP_ENABLED 0x2
+
void e1000_tbi_adjust_stats_82543(struct e1000_hw *hw,
- struct e1000_hw_stats *stats,
- u32 frame_len, u8 *mac_addr,
- u32 max_frame_size);
+ struct e1000_hw_stats *stats,
+ u32 frame_len, u8 *mac_addr,
+ u32 max_frame_size);
void e1000_set_tbi_compatibility_82543(struct e1000_hw *hw,
- bool state);
+ bool state);
bool e1000_tbi_sbp_enabled_82543(struct e1000_hw *hw);
#endif
diff --git a/usr/src/uts/common/io/e1000api/e1000_82571.c b/usr/src/uts/common/io/e1000api/e1000_82571.c
index e209d43826..a64ef56917 100644
--- a/usr/src/uts/common/io/e1000api/e1000_82571.c
+++ b/usr/src/uts/common/io/e1000api/e1000_82571.c
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2014, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/usr/src/uts/common/io/e1000api/e1000_82571.h b/usr/src/uts/common/io/e1000api/e1000_82571.h
index 41d5df0e13..8e5ca56ae8 100644
--- a/usr/src/uts/common/io/e1000api/e1000_82571.h
+++ b/usr/src/uts/common/io/e1000api/e1000_82571.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2014, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/usr/src/uts/common/io/e1000api/e1000_82575.c b/usr/src/uts/common/io/e1000api/e1000_82575.c
index 02f2590d4f..7c72bcf2c2 100644
--- a/usr/src/uts/common/io/e1000api/e1000_82575.c
+++ b/usr/src/uts/common/io/e1000api/e1000_82575.c
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2014, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -278,6 +278,11 @@ static s32 e1000_init_phy_params_82575(struct e1000_hw *hw)
if (ret_val)
goto out;
}
+ if (phy->id == M88E1543_E_PHY_ID) {
+ ret_val = e1000_initialize_M88E1543_phy(hw);
+ if (ret_val)
+ goto out;
+ }
break;
case IGP03E1000_E_PHY_ID:
case IGP04E1000_E_PHY_ID:
@@ -1051,7 +1056,7 @@ static s32 e1000_acquire_swfw_sync_82575(struct e1000_hw *hw, u16 mask)
u32 swmask = mask;
u32 fwmask = mask << 16;
s32 ret_val = E1000_SUCCESS;
- s32 i = 0, timeout = 200; /* FIXME: find real value to use here */
+ s32 i = 0, timeout = 200;
DEBUGFUNC("e1000_acquire_swfw_sync_82575");
@@ -1235,7 +1240,7 @@ static s32 e1000_check_for_link_media_swap(struct e1000_hw *hw)
DEBUGFUNC("e1000_check_for_link_media_swap");
- /* Check the copper medium. */
+ /* Check for copper. */
ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 0);
if (ret_val)
return ret_val;
@@ -1247,7 +1252,7 @@ static s32 e1000_check_for_link_media_swap(struct e1000_hw *hw)
if (data & E1000_M88E1112_STATUS_LINK)
port = E1000_MEDIA_PORT_COPPER;
- /* Check the other medium. */
+ /* Check for other. */
ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 1);
if (ret_val)
return ret_val;
@@ -1256,11 +1261,6 @@ static s32 e1000_check_for_link_media_swap(struct e1000_hw *hw)
if (ret_val)
return ret_val;
- /* reset page to 0 */
- ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 0);
- if (ret_val)
- return ret_val;
-
if (data & E1000_M88E1112_STATUS_LINK)
port = E1000_MEDIA_PORT_OTHER;
@@ -1268,8 +1268,20 @@ static s32 e1000_check_for_link_media_swap(struct e1000_hw *hw)
if (port && (hw->dev_spec._82575.media_port != port)) {
hw->dev_spec._82575.media_port = port;
hw->dev_spec._82575.media_changed = TRUE;
+ }
+
+ if (port == E1000_MEDIA_PORT_COPPER) {
+ /* reset page to 0 */
+ ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 0);
+ if (ret_val)
+ return ret_val;
+ e1000_check_for_link_82575(hw);
} else {
- ret_val = e1000_check_for_link_82575(hw);
+ e1000_check_for_link_82575(hw);
+ /* reset page to 0 */
+ ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 0);
+ if (ret_val)
+ return ret_val;
}
return E1000_SUCCESS;
@@ -2126,7 +2138,7 @@ static void e1000_clear_hw_cntrs_82575(struct e1000_hw *hw)
* e1000_rx_fifo_flush_82575 - Clean rx fifo after Rx enable
* @hw: pointer to the HW structure
*
- * After rx enable if managability is enabled then there is likely some
+ * After Rx enable, if manageability is enabled then there is likely some
* bad data at the start of the fifo and possibly in the DMA fifo. This
* function clears the fifos and flushes any packets that came in as rx was
* being enabled.
@@ -2136,7 +2148,13 @@ void e1000_rx_fifo_flush_82575(struct e1000_hw *hw)
u32 rctl, rlpml, rxdctl[4], rfctl, temp_rctl, rx_enabled;
int i, ms_wait;
- DEBUGFUNC("e1000_rx_fifo_workaround_82575");
+ DEBUGFUNC("e1000_rx_fifo_flush_82575");
+
+ /* disable IPv6 options as per hardware errata */
+ rfctl = E1000_READ_REG(hw, E1000_RFCTL);
+ rfctl |= E1000_RFCTL_IPV6_EX_DIS;
+ E1000_WRITE_REG(hw, E1000_RFCTL, rfctl);
+
if (hw->mac.type != e1000_82575 ||
!(E1000_READ_REG(hw, E1000_MANC) & E1000_MANC_RCV_TCO_EN))
return;
@@ -2164,7 +2182,6 @@ void e1000_rx_fifo_flush_82575(struct e1000_hw *hw)
* incoming packets are rejected. Set enable and wait 2ms so that
* any packet that was coming in as RCTL.EN was set is flushed
*/
- rfctl = E1000_READ_REG(hw, E1000_RFCTL);
E1000_WRITE_REG(hw, E1000_RFCTL, rfctl & ~E1000_RFCTL_LEF);
rlpml = E1000_READ_REG(hw, E1000_RLPML);
@@ -2806,7 +2823,7 @@ s32 e1000_read_emi_reg(struct e1000_hw *hw, u16 addr, u16 *data)
* e1000_initialize_M88E1512_phy - Initialize M88E1512 PHY
* @hw: pointer to the HW structure
*
- * Initialize Marverl 1512 to work correctly with Avoton.
+ * Initialize Marvell 1512 to work correctly with Avoton.
**/
s32 e1000_initialize_M88E1512_phy(struct e1000_hw *hw)
{
@@ -2892,13 +2909,114 @@ out:
}
/**
+ * e1000_initialize_M88E1543_phy - Initialize M88E1543 PHY
+ * @hw: pointer to the HW structure
+ *
+ * Initialize Marvell 1543 to work correctly with Avoton.
+ **/
+s32 e1000_initialize_M88E1543_phy(struct e1000_hw *hw)
+{
+ struct e1000_phy_info *phy = &hw->phy;
+ s32 ret_val = E1000_SUCCESS;
+
+ DEBUGFUNC("e1000_initialize_M88E1543_phy");
+
+ /* Check if this is correct PHY. */
+ if (phy->id != M88E1543_E_PHY_ID)
+ goto out;
+
+ /* Switch to PHY page 0xFF. */
+ ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0x00FF);
+ if (ret_val)
+ goto out;
+
+ ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_2, 0x214B);
+ if (ret_val)
+ goto out;
+
+ ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_1, 0x2144);
+ if (ret_val)
+ goto out;
+
+ ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_2, 0x0C28);
+ if (ret_val)
+ goto out;
+
+ ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_1, 0x2146);
+ if (ret_val)
+ goto out;
+
+ ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_2, 0xB233);
+ if (ret_val)
+ goto out;
+
+ ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_1, 0x214D);
+ if (ret_val)
+ goto out;
+
+ ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_2, 0xDC0C);
+ if (ret_val)
+ goto out;
+
+ ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_1, 0x2159);
+ if (ret_val)
+ goto out;
+
+ /* Switch to PHY page 0xFB. */
+ ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0x00FB);
+ if (ret_val)
+ goto out;
+
+ ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_3, 0xC00D);
+ if (ret_val)
+ goto out;
+
+ /* Switch to PHY page 0x12. */
+ ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0x12);
+ if (ret_val)
+ goto out;
+
+ /* Change mode to SGMII-to-Copper */
+ ret_val = phy->ops.write_reg(hw, E1000_M88E1512_MODE, 0x8001);
+ if (ret_val)
+ goto out;
+
+ /* Switch to PHY page 1. */
+ ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0x1);
+ if (ret_val)
+ goto out;
+
+ /* Change mode to 1000BASE-X/SGMII and autoneg enable; reset */
+ ret_val = phy->ops.write_reg(hw, E1000_M88E1543_FIBER_CTRL, 0x9140);
+ if (ret_val)
+ goto out;
+
+ /* Return the PHY to page 0. */
+ ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0);
+ if (ret_val)
+ goto out;
+
+ ret_val = phy->ops.commit(hw);
+ if (ret_val) {
+ DEBUGOUT("Error committing the PHY changes\n");
+ return ret_val;
+ }
+
+ msec_delay(1000);
+out:
+ return ret_val;
+}
+
+/**
* e1000_set_eee_i350 - Enable/disable EEE support
* @hw: pointer to the HW structure
+ * @adv1g: boolean flag enabling 1G EEE advertisement
+ * @adv100m: boolean flag enabling 100M EEE advertisement
*
* Enable/disable EEE based on setting in dev_spec structure.
*
**/
-s32 e1000_set_eee_i350(struct e1000_hw *hw)
+s32 e1000_set_eee_i350(struct e1000_hw *hw, bool adv1G, bool adv100M)
{
u32 ipcnfg, eeer;
@@ -2914,7 +3032,16 @@ s32 e1000_set_eee_i350(struct e1000_hw *hw)
if (!(hw->dev_spec._82575.eee_disable)) {
u32 eee_su = E1000_READ_REG(hw, E1000_EEE_SU);
- ipcnfg |= (E1000_IPCNFG_EEE_1G_AN | E1000_IPCNFG_EEE_100M_AN);
+ if (adv100M)
+ ipcnfg |= E1000_IPCNFG_EEE_100M_AN;
+ else
+ ipcnfg &= ~E1000_IPCNFG_EEE_100M_AN;
+
+ if (adv1G)
+ ipcnfg |= E1000_IPCNFG_EEE_1G_AN;
+ else
+ ipcnfg &= ~E1000_IPCNFG_EEE_1G_AN;
+
eeer |= (E1000_EEER_TX_LPI_EN | E1000_EEER_RX_LPI_EN |
E1000_EEER_LPI_FC);
@@ -2938,11 +3065,13 @@ out:
/**
* e1000_set_eee_i354 - Enable/disable EEE support
* @hw: pointer to the HW structure
+ * @adv1g: boolean flag enabling 1G EEE advertisement
+ * @adv100m: boolean flag enabling 100M EEE advertisement
*
* Enable/disable EEE legacy mode based on setting in dev_spec structure.
*
**/
-s32 e1000_set_eee_i354(struct e1000_hw *hw)
+s32 e1000_set_eee_i354(struct e1000_hw *hw, bool adv1G, bool adv100M)
{
struct e1000_phy_info *phy = &hw->phy;
s32 ret_val = E1000_SUCCESS;
@@ -2984,8 +3113,16 @@ s32 e1000_set_eee_i354(struct e1000_hw *hw)
if (ret_val)
goto out;
- phy_data |= E1000_EEE_ADV_100_SUPPORTED |
- E1000_EEE_ADV_1000_SUPPORTED;
+ if (adv100M)
+ phy_data |= E1000_EEE_ADV_100_SUPPORTED;
+ else
+ phy_data &= ~E1000_EEE_ADV_100_SUPPORTED;
+
+ if (adv1G)
+ phy_data |= E1000_EEE_ADV_1000_SUPPORTED;
+ else
+ phy_data &= ~E1000_EEE_ADV_1000_SUPPORTED;
+
ret_val = e1000_write_xmdio_reg(hw, E1000_EEE_ADV_ADDR_I354,
E1000_EEE_ADV_DEV_I354,
phy_data);
diff --git a/usr/src/uts/common/io/e1000api/e1000_82575.h b/usr/src/uts/common/io/e1000api/e1000_82575.h
index bc550c06a4..e5f7aad3f6 100644
--- a/usr/src/uts/common/io/e1000api/e1000_82575.h
+++ b/usr/src/uts/common/io/e1000api/e1000_82575.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2014, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -35,10 +35,6 @@
#ifndef _E1000_82575_H_
#define _E1000_82575_H_
-#ifdef __cplusplus
-extern "C" {
-#endif
-
#define ID_LED_DEFAULT_82575_SERDES ((ID_LED_DEF1_DEF2 << 12) | \
(ID_LED_DEF1_DEF2 << 8) | \
(ID_LED_DEF1_DEF2 << 4) | \
@@ -499,10 +495,11 @@ void e1000_rlpml_set_vf(struct e1000_hw *, u16);
s32 e1000_promisc_set_vf(struct e1000_hw *, enum e1000_promisc_type type);
u16 e1000_rxpbs_adjust_82580(u32 data);
s32 e1000_read_emi_reg(struct e1000_hw *hw, u16 addr, u16 *data);
-s32 e1000_set_eee_i350(struct e1000_hw *);
-s32 e1000_set_eee_i354(struct e1000_hw *);
+s32 e1000_set_eee_i350(struct e1000_hw *hw, bool adv1G, bool adv100M);
+s32 e1000_set_eee_i354(struct e1000_hw *hw, bool adv1G, bool adv100M);
s32 e1000_get_eee_status_i354(struct e1000_hw *, bool *);
s32 e1000_initialize_M88E1512_phy(struct e1000_hw *hw);
+s32 e1000_initialize_M88E1543_phy(struct e1000_hw *hw);
/* I2C SDA and SCL timing parameters for standard mode */
#define E1000_I2C_T_HD_STA 4
@@ -522,9 +519,4 @@ s32 e1000_read_i2c_byte_generic(struct e1000_hw *hw, u8 byte_offset,
s32 e1000_write_i2c_byte_generic(struct e1000_hw *hw, u8 byte_offset,
u8 dev_addr, u8 data);
void e1000_i2c_bus_clear(struct e1000_hw *hw);
-
-#ifdef __cplusplus
-}
-#endif
-
#endif /* _E1000_82575_H_ */
diff --git a/usr/src/uts/common/io/e1000api/e1000_api.c b/usr/src/uts/common/io/e1000api/e1000_api.c
index 374ffa678e..28379cc572 100644
--- a/usr/src/uts/common/io/e1000api/e1000_api.c
+++ b/usr/src/uts/common/io/e1000api/e1000_api.c
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2014, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -299,6 +299,13 @@ s32 e1000_set_mac_type(struct e1000_hw *hw)
case E1000_DEV_ID_PCH_I218_V3:
mac->type = e1000_pch_lpt;
break;
+ case E1000_DEV_ID_PCH_SPT_I219_LM:
+ case E1000_DEV_ID_PCH_SPT_I219_V:
+ case E1000_DEV_ID_PCH_SPT_I219_LM2:
+ case E1000_DEV_ID_PCH_SPT_I219_V2:
+ case E1000_DEV_ID_PCH_LBG_I219_LM3:
+ mac->type = e1000_pch_spt;
+ break;
case E1000_DEV_ID_82575EB_COPPER:
case E1000_DEV_ID_82575EB_FIBER_SERDES:
case E1000_DEV_ID_82575GB_QUAD_COPPER:
@@ -449,6 +456,7 @@ s32 e1000_setup_init_funcs(struct e1000_hw *hw, bool init_device)
case e1000_pchlan:
case e1000_pch2lan:
case e1000_pch_lpt:
+ case e1000_pch_spt:
e1000_init_function_pointers_ich8lan(hw);
break;
case e1000_82575:
diff --git a/usr/src/uts/common/io/e1000api/e1000_api.h b/usr/src/uts/common/io/e1000api/e1000_api.h
index a2ffa16936..074197bfe8 100644
--- a/usr/src/uts/common/io/e1000api/e1000_api.h
+++ b/usr/src/uts/common/io/e1000api/e1000_api.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2014, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -124,14 +124,14 @@ u32 e1000_translate_register_82542(u32 reg);
* TBI_ACCEPT macro definition:
*
* This macro requires:
- * adapter = a pointer to struct e1000_hw
+ * a = a pointer to struct e1000_hw
* status = the 8 bit status field of the Rx descriptor with EOP set
- * error = the 8 bit error field of the Rx descriptor with EOP set
+ * errors = the 8 bit error field of the Rx descriptor with EOP set
* length = the sum of all the length fields of the Rx descriptors that
* make up the current frame
* last_byte = the last byte of the frame DMAed by the hardware
- * max_frame_length = the maximum frame length we want to accept.
- * min_frame_length = the minimum frame length we want to accept.
+ * min_frame_size = the minimum frame length we want to accept.
+ * max_frame_size = the maximum frame length we want to accept.
*
* This macro is a conditional that should be used in the interrupt
* handler's Rx processing routine when RxErrors have been detected.
@@ -157,10 +157,10 @@ u32 e1000_translate_register_82542(u32 reg);
(((errors) & E1000_RXD_ERR_FRAME_ERR_MASK) == E1000_RXD_ERR_CE) && \
((last_byte) == CARRIER_EXTENSION) && \
(((status) & E1000_RXD_STAT_VP) ? \
- (((length) > (min_frame_size - VLAN_TAG_SIZE)) && \
- ((length) <= (max_frame_size + 1))) : \
- (((length) > min_frame_size) && \
- ((length) <= (max_frame_size + VLAN_TAG_SIZE + 1)))))
+ (((length) > ((min_frame_size) - VLAN_TAG_SIZE)) && \
+ ((length) <= ((max_frame_size) + 1))) : \
+ (((length) > (min_frame_size)) && \
+ ((length) <= ((max_frame_size) + VLAN_TAG_SIZE + 1)))))
#define E1000_MAX(a, b) ((a) > (b) ? (a) : (b))
#define E1000_DIVIDE_ROUND_UP(a, b) (((a) + (b) - 1) / (b)) /* ceil(a/b) */
diff --git a/usr/src/uts/common/io/e1000api/e1000_defines.h b/usr/src/uts/common/io/e1000api/e1000_defines.h
index b0faf8c0d2..b49cf450f5 100644
--- a/usr/src/uts/common/io/e1000api/e1000_defines.h
+++ b/usr/src/uts/common/io/e1000api/e1000_defines.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2014, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -158,11 +158,12 @@
E1000_RXDEXT_STATERR_CXE | \
E1000_RXDEXT_STATERR_RXE)
-#define E1000_MRQC_ENABLE_RSS_2Q 0x00000001
+#define E1000_MRQC_RSS_ENABLE_2Q 0x00000001
#define E1000_MRQC_RSS_FIELD_MASK 0xFFFF0000
#define E1000_MRQC_RSS_FIELD_IPV4_TCP 0x00010000
#define E1000_MRQC_RSS_FIELD_IPV4 0x00020000
#define E1000_MRQC_RSS_FIELD_IPV6_TCP_EX 0x00040000
+#define E1000_MRQC_RSS_FIELD_IPV6_EX 0x00080000
#define E1000_MRQC_RSS_FIELD_IPV6 0x00100000
#define E1000_MRQC_RSS_FIELD_IPV6_TCP 0x00200000
@@ -196,6 +197,8 @@
#define E1000_RCTL_LBM_TCVR 0x000000C0 /* tcvr loopback mode */
#define E1000_RCTL_DTYP_PS 0x00000400 /* Packet Split descriptor */
#define E1000_RCTL_RDMTS_HALF 0x00000000 /* Rx desc min thresh size */
+#define E1000_RCTL_RDMTS_HEX 0x00010000
+#define E1000_RCTL_RDMTS1_HEX E1000_RCTL_RDMTS_HEX
#define E1000_RCTL_MO_SHIFT 12 /* multicast offset shift */
#define E1000_RCTL_MO_3 0x00003000 /* multicast offset 15:4 */
#define E1000_RCTL_BAM 0x00008000 /* broadcast enable */
@@ -752,6 +755,12 @@
#define E1000_TSYNCTXCTL_VALID 0x00000001 /* Tx timestamp valid */
#define E1000_TSYNCTXCTL_ENABLED 0x00000010 /* enable Tx timestamping */
+/* HH Time Sync */
+#define E1000_TSYNCTXCTL_MAX_ALLOWED_DLY_MASK 0x0000F000 /* max delay */
+#define E1000_TSYNCTXCTL_SYNC_COMP_ERR 0x20000000 /* sync err */
+#define E1000_TSYNCTXCTL_SYNC_COMP 0x40000000 /* sync complete */
+#define E1000_TSYNCTXCTL_START_SYNC 0x80000000 /* initiate sync */
+
#define E1000_TSYNCRXCTL_VALID 0x00000001 /* Rx timestamp valid */
#define E1000_TSYNCRXCTL_TYPE_MASK 0x0000000E /* Rx type mask */
#define E1000_TSYNCRXCTL_TYPE_L2_V2 0x00
@@ -848,6 +857,7 @@
#define E1000_M88E1543_PAGE_ADDR 0x16 /* Page Offset Register */
#define E1000_M88E1543_EEE_CTRL_1 0x0
#define E1000_M88E1543_EEE_CTRL_1_MS 0x0001 /* EEE Master/Slave */
+#define E1000_M88E1543_FIBER_CTRL 0x0 /* Fiber Control Register */
#define E1000_EEE_ADV_DEV_I354 7
#define E1000_EEE_ADV_ADDR_I354 60
#define E1000_EEE_ADV_100_SUPPORTED (1 << 1) /* 100BaseTx EEE Supported */
@@ -1019,9 +1029,7 @@
/* NVM Addressing bits based on type 0=small, 1=large */
#define E1000_EECD_ADDR_BITS 0x00000400
#define E1000_EECD_TYPE 0x00002000 /* NVM Type (1-SPI, 0-Microwire) */
-#ifndef E1000_NVM_GRANT_ATTEMPTS
#define E1000_NVM_GRANT_ATTEMPTS 1000 /* NVM # attempts to gain grant */
-#endif
#define E1000_EECD_AUTO_RD 0x00000200 /* NVM Auto Read done */
#define E1000_EECD_SIZE_EX_MASK 0x00007800 /* NVM Size */
#define E1000_EECD_SIZE_EX_SHIFT 11
@@ -1058,7 +1066,6 @@
/* NVM Word Offsets */
#define NVM_COMPAT 0x0003
#define NVM_ID_LED_SETTINGS 0x0004
-#define NVM_VERSION 0x0005
#define NVM_SERDES_AMPLITUDE 0x0006 /* SERDES output amplitude */
#define NVM_PHY_CLASS_WORD 0x0007
#define E1000_I210_NVM_FW_MODULE_PTR 0x0010
@@ -1122,10 +1129,6 @@
/* For checksumming, the sum of all words in the NVM should equal 0xBABA. */
#define NVM_SUM 0xBABA
-/* OEM NVM Offsets */
-#define NVM_OEM_OFFSET_0 6
-#define NVM_OEM_OFFSET_1 7
-
/* PBA (printed board assembly) number words */
#define NVM_PBA_OFFSET_0 8
#define NVM_PBA_OFFSET_1 9
@@ -1473,4 +1476,12 @@
#ifndef ERROR_REPORT
#define ERROR_REPORT(fmt) do { } while (0)
#endif /* ERROR_REPORT */
+
+/*
+ * illumos additions
+ */
+#define NVM_VERSION 0x0005
+#define NVM_OEM_OFFSET_0 6
+#define NVM_OEM_OFFSET_1 7
+
#endif /* _E1000_DEFINES_H_ */
diff --git a/usr/src/uts/common/io/e1000api/e1000_hw.h b/usr/src/uts/common/io/e1000api/e1000_hw.h
index 9ceb0b891f..4ee1c3b07f 100644
--- a/usr/src/uts/common/io/e1000api/e1000_hw.h
+++ b/usr/src/uts/common/io/e1000api/e1000_hw.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2014, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -35,10 +35,6 @@
#ifndef _E1000_HW_H_
#define _E1000_HW_H_
-#ifdef __cplusplus
-extern "C" {
-#endif
-
#include "e1000_osdep.h"
#include "e1000_regs.h"
#include "e1000_defines.h"
@@ -141,6 +137,11 @@ struct e1000_hw;
#define E1000_DEV_ID_PCH_I218_V2 0x15A1
#define E1000_DEV_ID_PCH_I218_LM3 0x15A2 /* Wildcat Point PCH */
#define E1000_DEV_ID_PCH_I218_V3 0x15A3 /* Wildcat Point PCH */
+#define E1000_DEV_ID_PCH_SPT_I219_LM 0x156F /* Sunrise Point PCH */
+#define E1000_DEV_ID_PCH_SPT_I219_V 0x1570 /* Sunrise Point PCH */
+#define E1000_DEV_ID_PCH_SPT_I219_LM2 0x15B7 /* Sunrise Point-H PCH */
+#define E1000_DEV_ID_PCH_SPT_I219_V2 0x15B8 /* Sunrise Point-H PCH */
+#define E1000_DEV_ID_PCH_LBG_I219_LM3 0x15B9 /* LEWISBURG PCH */
#define E1000_DEV_ID_82576 0x10C9
#define E1000_DEV_ID_82576_FIBER 0x10E6
#define E1000_DEV_ID_82576_SERDES 0x10E7
@@ -226,6 +227,7 @@ enum e1000_mac_type {
e1000_pchlan,
e1000_pch2lan,
e1000_pch_lpt,
+ e1000_pch_spt,
e1000_82575,
e1000_82576,
e1000_82580,
@@ -791,7 +793,7 @@ struct e1000_mac_info {
u16 uta_reg_count;
/* Maximum size of the MTA register table in all supported adapters */
- #define MAX_MTA_REG 128
+#define MAX_MTA_REG 128
u32 mta_shadow[MAX_MTA_REG];
u16 rar_entry_count;
@@ -809,7 +811,7 @@ struct e1000_mac_info {
enum e1000_serdes_link_state serdes_link_state;
bool serdes_has_link;
bool tx_pkt_filtering;
- u32 max_frame_size;
+ u32 max_frame_size;
};
struct e1000_phy_info {
@@ -1032,8 +1034,4 @@ s32 e1000_write_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value);
void e1000_read_pci_cfg(struct e1000_hw *hw, u32 reg, u16 *value);
void e1000_write_pci_cfg(struct e1000_hw *hw, u32 reg, u16 *value);
-#ifdef __cplusplus
-}
#endif
-
-#endif /* _E1000_HW_H_ */
diff --git a/usr/src/uts/common/io/e1000api/e1000_i210.c b/usr/src/uts/common/io/e1000api/e1000_i210.c
index f12c13f0ca..cd8d7c7e1f 100644
--- a/usr/src/uts/common/io/e1000api/e1000_i210.c
+++ b/usr/src/uts/common/io/e1000api/e1000_i210.c
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2014, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -883,6 +883,35 @@ static s32 e1000_pll_workaround_i210(struct e1000_hw *hw)
}
/**
+ * e1000_get_cfg_done_i210 - Read config done bit
+ * @hw: pointer to the HW structure
+ *
+ * Read the management control register for the config done bit for
+ * completion status. NOTE: silicon which is EEPROM-less will fail trying
+ * to read the config done bit, so an error is *ONLY* logged and returns
+ * E1000_SUCCESS. If we were to return with error, EEPROM-less silicon
+ * would not be able to be reset or change link.
+ **/
+static s32 e1000_get_cfg_done_i210(struct e1000_hw *hw)
+{
+ s32 timeout = PHY_CFG_TIMEOUT;
+ u32 mask = E1000_NVM_CFG_DONE_PORT_0;
+
+ DEBUGFUNC("e1000_get_cfg_done_i210");
+
+ while (timeout) {
+ if (E1000_READ_REG(hw, E1000_EEMNGCTL_I210) & mask)
+ break;
+ msec_delay(1);
+ timeout--;
+ }
+ if (!timeout)
+ DEBUGOUT("MNG configuration cycle has not completed.\n");
+
+ return E1000_SUCCESS;
+}
+
+/**
* e1000_init_hw_i210 - Init hw for I210/I211
* @hw: pointer to the HW structure
*
@@ -899,6 +928,7 @@ s32 e1000_init_hw_i210(struct e1000_hw *hw)
if (ret_val != E1000_SUCCESS)
return ret_val;
}
+ hw->phy.ops.get_cfg_done = e1000_get_cfg_done_i210;
ret_val = e1000_init_hw_82575(hw);
return ret_val;
}
diff --git a/usr/src/uts/common/io/e1000api/e1000_i210.h b/usr/src/uts/common/io/e1000api/e1000_i210.h
index 2a20ca1e6e..f940915b06 100644
--- a/usr/src/uts/common/io/e1000api/e1000_i210.h
+++ b/usr/src/uts/common/io/e1000api/e1000_i210.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2014, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/usr/src/uts/common/io/e1000api/e1000_ich8lan.c b/usr/src/uts/common/io/e1000api/e1000_ich8lan.c
index 14c5689edb..c042602585 100644
--- a/usr/src/uts/common/io/e1000api/e1000_ich8lan.c
+++ b/usr/src/uts/common/io/e1000api/e1000_ich8lan.c
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2014, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -92,10 +92,13 @@ static s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw,
bool active);
static s32 e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset,
u16 words, u16 *data);
+static s32 e1000_read_nvm_spt(struct e1000_hw *hw, u16 offset, u16 words,
+ u16 *data);
static s32 e1000_write_nvm_ich8lan(struct e1000_hw *hw, u16 offset,
u16 words, u16 *data);
static s32 e1000_validate_nvm_checksum_ich8lan(struct e1000_hw *hw);
static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw);
+static s32 e1000_update_nvm_checksum_spt(struct e1000_hw *hw);
static s32 e1000_valid_led_default_ich8lan(struct e1000_hw *hw,
u16 *data);
static s32 e1000_id_led_init_pchlan(struct e1000_hw *hw);
@@ -123,6 +126,14 @@ static s32 e1000_read_flash_byte_ich8lan(struct e1000_hw *hw,
u32 offset, u8 *data);
static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
u8 size, u16 *data);
+static s32 e1000_read_flash_data32_ich8lan(struct e1000_hw *hw, u32 offset,
+ u32 *data);
+static s32 e1000_read_flash_dword_ich8lan(struct e1000_hw *hw,
+ u32 offset, u32 *data);
+static s32 e1000_write_flash_data32_ich8lan(struct e1000_hw *hw,
+ u32 offset, u32 data);
+static s32 e1000_retry_write_flash_dword_ich8lan(struct e1000_hw *hw,
+ u32 offset, u32 dword);
static s32 e1000_read_flash_word_ich8lan(struct e1000_hw *hw,
u32 offset, u16 *data);
static s32 e1000_retry_write_flash_byte_ich8lan(struct e1000_hw *hw,
@@ -232,16 +243,21 @@ static bool e1000_phy_is_accessible_pchlan(struct e1000_hw *hw)
if (ret_val)
return FALSE;
out:
- if (hw->mac.type == e1000_pch_lpt) {
- /* Unforce SMBus mode in PHY */
- hw->phy.ops.read_reg_locked(hw, CV_SMB_CTRL, &phy_reg);
- phy_reg &= ~CV_SMB_CTRL_FORCE_SMBUS;
- hw->phy.ops.write_reg_locked(hw, CV_SMB_CTRL, phy_reg);
+ if ((hw->mac.type == e1000_pch_lpt) ||
+ (hw->mac.type == e1000_pch_spt)) {
+ /* Only unforce SMBus if ME is not active */
+ if (!(E1000_READ_REG(hw, E1000_FWSM) &
+ E1000_ICH_FWSM_FW_VALID)) {
+ /* Unforce SMBus mode in PHY */
+ hw->phy.ops.read_reg_locked(hw, CV_SMB_CTRL, &phy_reg);
+ phy_reg &= ~CV_SMB_CTRL_FORCE_SMBUS;
+ hw->phy.ops.write_reg_locked(hw, CV_SMB_CTRL, phy_reg);
- /* Unforce SMBus mode in MAC */
- mac_reg = E1000_READ_REG(hw, E1000_CTRL_EXT);
- mac_reg &= ~E1000_CTRL_EXT_FORCE_SMBUS;
- E1000_WRITE_REG(hw, E1000_CTRL_EXT, mac_reg);
+ /* Unforce SMBus mode in MAC */
+ mac_reg = E1000_READ_REG(hw, E1000_CTRL_EXT);
+ mac_reg &= ~E1000_CTRL_EXT_FORCE_SMBUS;
+ E1000_WRITE_REG(hw, E1000_CTRL_EXT, mac_reg);
+ }
}
return TRUE;
@@ -328,6 +344,7 @@ static s32 e1000_init_phy_workarounds_pchlan(struct e1000_hw *hw)
*/
switch (hw->mac.type) {
case e1000_pch_lpt:
+ case e1000_pch_spt:
if (e1000_phy_is_accessible_pchlan(hw))
break;
@@ -475,6 +492,7 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)
/* fall-through */
case e1000_pch2lan:
case e1000_pch_lpt:
+ case e1000_pch_spt:
/* In case the PHY needs to be in mdio slow mode,
* set slow mode and try to get the PHY id again.
*/
@@ -617,36 +635,57 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw)
struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
u32 gfpreg, sector_base_addr, sector_end_addr;
u16 i;
+ u32 nvm_size;
DEBUGFUNC("e1000_init_nvm_params_ich8lan");
- /* Can't read flash registers if the register set isn't mapped. */
nvm->type = e1000_nvm_flash_sw;
- if (!hw->flash_address) {
- DEBUGOUT("ERROR: Flash registers not mapped\n");
- return -E1000_ERR_CONFIG;
- }
- gfpreg = E1000_READ_FLASH_REG(hw, ICH_FLASH_GFPREG);
+ if (hw->mac.type == e1000_pch_spt) {
+ /* in SPT, gfpreg doesn't exist. NVM size is taken from the
+ * STRAP register. This is because in SPT the GbE Flash region
+ * is no longer accessed through the flash registers. Instead,
+ * the mechanism has changed, and the Flash region access
+ * registers are now implemented in GbE memory space.
+ */
+ nvm->flash_base_addr = 0;
+ nvm_size =
+ (((E1000_READ_REG(hw, E1000_STRAP) >> 1) & 0x1F) + 1)
+ * NVM_SIZE_MULTIPLIER;
+ nvm->flash_bank_size = nvm_size / 2;
+ /* Adjust to word count */
+ nvm->flash_bank_size /= sizeof(u16);
+ /* Set the base address for flash register access */
+ hw->flash_address = hw->hw_addr + E1000_FLASH_BASE_ADDR;
+ } else {
+ /* Can't read flash registers if register set isn't mapped. */
+ if (!hw->flash_address) {
+ DEBUGOUT("ERROR: Flash registers not mapped\n");
+ return -E1000_ERR_CONFIG;
+ }
- /* sector_X_addr is a "sector"-aligned address (4096 bytes)
- * Add 1 to sector_end_addr since this sector is included in
- * the overall size.
- */
- sector_base_addr = gfpreg & FLASH_GFPREG_BASE_MASK;
- sector_end_addr = ((gfpreg >> 16) & FLASH_GFPREG_BASE_MASK) + 1;
+ gfpreg = E1000_READ_FLASH_REG(hw, ICH_FLASH_GFPREG);
- /* flash_base_addr is byte-aligned */
- nvm->flash_base_addr = sector_base_addr << FLASH_SECTOR_ADDR_SHIFT;
+ /* sector_X_addr is a "sector"-aligned address (4096 bytes)
+ * Add 1 to sector_end_addr since this sector is included in
+ * the overall size.
+ */
+ sector_base_addr = gfpreg & FLASH_GFPREG_BASE_MASK;
+ sector_end_addr = ((gfpreg >> 16) & FLASH_GFPREG_BASE_MASK) + 1;
- /* find total size of the NVM, then cut in half since the total
- * size represents two separate NVM banks.
- */
- nvm->flash_bank_size = ((sector_end_addr - sector_base_addr)
- << FLASH_SECTOR_ADDR_SHIFT);
- nvm->flash_bank_size /= 2;
- /* Adjust to word count */
- nvm->flash_bank_size /= sizeof(u16);
+ /* flash_base_addr is byte-aligned */
+ nvm->flash_base_addr = sector_base_addr
+ << FLASH_SECTOR_ADDR_SHIFT;
+
+ /* find total size of the NVM, then cut in half since the total
+ * size represents two separate NVM banks.
+ */
+ nvm->flash_bank_size = ((sector_end_addr - sector_base_addr)
+ << FLASH_SECTOR_ADDR_SHIFT);
+ nvm->flash_bank_size /= 2;
+ /* Adjust to word count */
+ nvm->flash_bank_size /= sizeof(u16);
+ }
nvm->word_size = E1000_SHADOW_RAM_WORDS;
@@ -662,8 +701,13 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw)
/* Function Pointers */
nvm->ops.acquire = e1000_acquire_nvm_ich8lan;
nvm->ops.release = e1000_release_nvm_ich8lan;
- nvm->ops.read = e1000_read_nvm_ich8lan;
- nvm->ops.update = e1000_update_nvm_checksum_ich8lan;
+ if (hw->mac.type == e1000_pch_spt) {
+ nvm->ops.read = e1000_read_nvm_spt;
+ nvm->ops.update = e1000_update_nvm_checksum_spt;
+ } else {
+ nvm->ops.read = e1000_read_nvm_ich8lan;
+ nvm->ops.update = e1000_update_nvm_checksum_ich8lan;
+ }
nvm->ops.valid_led_default = e1000_valid_led_default_ich8lan;
nvm->ops.validate = e1000_validate_nvm_checksum_ich8lan;
nvm->ops.write = e1000_write_nvm_ich8lan;
@@ -749,9 +793,11 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw)
mac->ops.rar_set = e1000_rar_set_pch2lan;
/* fall-through */
case e1000_pch_lpt:
+ case e1000_pch_spt:
/* multicast address update for pch2 */
mac->ops.update_mc_addr_list =
e1000_update_mc_addr_list_pch2lan;
+ /* fall-through */
case e1000_pchlan:
/* check management mode */
mac->ops.check_mng_mode = e1000_check_mng_mode_pchlan;
@@ -769,7 +815,8 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw)
break;
}
- if (mac->type == e1000_pch_lpt) {
+ if ((mac->type == e1000_pch_lpt) ||
+ (mac->type == e1000_pch_spt)) {
mac->rar_entry_count = E1000_PCH_LPT_RAR_ENTRIES;
mac->ops.rar_set = e1000_rar_set_pch_lpt;
mac->ops.setup_physical_interface = e1000_setup_copper_link_pch_lpt;
@@ -999,8 +1046,9 @@ release:
/* clear FEXTNVM6 bit 8 on link down or 10/100 */
fextnvm6 &= ~E1000_FEXTNVM6_REQ_PLL_CLK;
- if (!link || ((status & E1000_STATUS_SPEED_100) &&
- (status & E1000_STATUS_FD)))
+ if ((hw->phy.revision > 5) || !link ||
+ ((status & E1000_STATUS_SPEED_100) &&
+ (status & E1000_STATUS_FD)))
goto update_fextnvm6;
ret_val = hw->phy.ops.read_reg(hw, I217_INBAND_CTRL, &reg);
@@ -1079,7 +1127,7 @@ static s32 e1000_platform_pm_pch_lpt(struct e1000_hw *hw, bool link)
u16 speed, duplex, scale = 0;
u16 max_snoop, max_nosnoop;
u16 max_ltr_enc; /* max LTR latency encoded */
- s64 lat_ns; /* latency (ns) */
+ s64 lat_ns;
s64 value;
u32 rxa;
@@ -1111,8 +1159,8 @@ static s32 e1000_platform_pm_pch_lpt(struct e1000_hw *hw, bool link)
lat_ns = 0;
else
lat_ns /= speed;
-
value = lat_ns;
+
while (value > E1000_LTRV_VALUE_MASK) {
scale++;
value = E1000_DIVIDE_ROUND_UP(value, (1 << 5));
@@ -1213,6 +1261,7 @@ s32 e1000_enable_ulp_lpt_lp(struct e1000_hw *hw, bool to_sx)
u32 mac_reg;
s32 ret_val = E1000_SUCCESS;
u16 phy_reg;
+ u16 oem_reg = 0;
if ((hw->mac.type < e1000_pch_lpt) ||
(hw->device_id == E1000_DEV_ID_PCH_LPT_I217_LM) ||
@@ -1268,6 +1317,25 @@ s32 e1000_enable_ulp_lpt_lp(struct e1000_hw *hw, bool to_sx)
mac_reg |= E1000_CTRL_EXT_FORCE_SMBUS;
E1000_WRITE_REG(hw, E1000_CTRL_EXT, mac_reg);
+ /* Si workaround for ULP entry flow on i127/rev6 h/w. Enable
+ * LPLU and disable Gig speed when entering ULP
+ */
+ if ((hw->phy.type == e1000_phy_i217) && (hw->phy.revision == 6)) {
+ ret_val = e1000_read_phy_reg_hv_locked(hw, HV_OEM_BITS,
+ &oem_reg);
+ if (ret_val)
+ goto release;
+
+ phy_reg = oem_reg;
+ phy_reg |= HV_OEM_BITS_LPLU | HV_OEM_BITS_GBE_DIS;
+
+ ret_val = e1000_write_phy_reg_hv_locked(hw, HV_OEM_BITS,
+ phy_reg);
+
+ if (ret_val)
+ goto release;
+ }
+
/* Set Inband ULP Exit, Reset to SMBus mode and
* Disable SMBus Release on PERST# in PHY
*/
@@ -1279,10 +1347,15 @@ s32 e1000_enable_ulp_lpt_lp(struct e1000_hw *hw, bool to_sx)
if (to_sx) {
if (E1000_READ_REG(hw, E1000_WUFC) & E1000_WUFC_LNKC)
phy_reg |= I218_ULP_CONFIG1_WOL_HOST;
+ else
+ phy_reg &= ~I218_ULP_CONFIG1_WOL_HOST;
phy_reg |= I218_ULP_CONFIG1_STICKY_ULP;
+ phy_reg &= ~I218_ULP_CONFIG1_INBAND_EXIT;
} else {
phy_reg |= I218_ULP_CONFIG1_INBAND_EXIT;
+ phy_reg &= ~I218_ULP_CONFIG1_STICKY_ULP;
+ phy_reg &= ~I218_ULP_CONFIG1_WOL_HOST;
}
e1000_write_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, phy_reg);
@@ -1294,12 +1367,21 @@ s32 e1000_enable_ulp_lpt_lp(struct e1000_hw *hw, bool to_sx)
/* Commit ULP changes in PHY by starting auto ULP configuration */
phy_reg |= I218_ULP_CONFIG1_START;
e1000_write_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, phy_reg);
+
+ if ((hw->phy.type == e1000_phy_i217) && (hw->phy.revision == 6) &&
+ to_sx && (E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_LU)) {
+ ret_val = e1000_write_phy_reg_hv_locked(hw, HV_OEM_BITS,
+ oem_reg);
+ if (ret_val)
+ goto release;
+ }
+
release:
hw->phy.ops.release(hw);
out:
- if (ret_val) {
+ if (ret_val)
DEBUGOUT1("Error in ULP enable flow: %d\n", ret_val);
- } else
+ else
hw->dev_spec.ich8lan.ulp_state = e1000_ulp_state_on;
return ret_val;
@@ -1344,10 +1426,10 @@ s32 e1000_disable_ulp_lpt_lp(struct e1000_hw *hw, bool force)
E1000_WRITE_REG(hw, E1000_H2ME, mac_reg);
}
- /* Poll up to 100msec for ME to clear ULP_CFG_DONE */
+ /* Poll up to 300msec for ME to clear ULP_CFG_DONE. */
while (E1000_READ_REG(hw, E1000_FWSM) &
E1000_FWSM_ULP_CFG_DONE) {
- if (i++ == 10) {
+ if (i++ == 30) {
ret_val = -E1000_ERR_PHY;
goto out;
}
@@ -1421,6 +1503,8 @@ s32 e1000_disable_ulp_lpt_lp(struct e1000_hw *hw, bool force)
I218_ULP_CONFIG1_RESET_TO_SMBUS |
I218_ULP_CONFIG1_WOL_HOST |
I218_ULP_CONFIG1_INBAND_EXIT |
+ I218_ULP_CONFIG1_EN_ULP_LANPHYPC |
+ I218_ULP_CONFIG1_DIS_CLR_STICKY_ON_PERST |
I218_ULP_CONFIG1_DISABLE_SMB_PERST);
e1000_write_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, phy_reg);
@@ -1440,9 +1524,9 @@ release:
msec_delay(50);
}
out:
- if (ret_val) {
+ if (ret_val)
DEBUGOUT1("Error in ULP disable flow: %d\n", ret_val);
- } else
+ else
hw->dev_spec.ich8lan.ulp_state = e1000_ulp_state_off;
return ret_val;
@@ -1459,7 +1543,8 @@ out:
static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
{
struct e1000_mac_info *mac = &hw->mac;
- s32 ret_val;
+ s32 ret_val, tipg_reg = 0;
+ u16 emi_addr, emi_val = 0;
bool link;
u16 phy_reg;
@@ -1492,35 +1577,119 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
* the IPG and reduce Rx latency in the PHY.
*/
if (((hw->mac.type == e1000_pch2lan) ||
- (hw->mac.type == e1000_pch_lpt)) && link) {
- u32 reg;
- reg = E1000_READ_REG(hw, E1000_STATUS);
- if (!(reg & (E1000_STATUS_FD | E1000_STATUS_SPEED_MASK))) {
- u16 emi_addr;
+ (hw->mac.type == e1000_pch_lpt) ||
+ (hw->mac.type == e1000_pch_spt)) && link) {
+ u16 speed, duplex;
- reg = E1000_READ_REG(hw, E1000_TIPG);
- reg &= ~E1000_TIPG_IPGT_MASK;
- reg |= 0xFF;
- E1000_WRITE_REG(hw, E1000_TIPG, reg);
+ e1000_get_speed_and_duplex_copper_generic(hw, &speed, &duplex);
+ tipg_reg = E1000_READ_REG(hw, E1000_TIPG);
+ tipg_reg &= ~E1000_TIPG_IPGT_MASK;
+ if (duplex == HALF_DUPLEX && speed == SPEED_10) {
+ tipg_reg |= 0xFF;
/* Reduce Rx latency in analog PHY */
- ret_val = hw->phy.ops.acquire(hw);
- if (ret_val)
- return ret_val;
+ emi_val = 0;
+ } else if (hw->mac.type == e1000_pch_spt &&
+ duplex == FULL_DUPLEX && speed != SPEED_1000) {
+ tipg_reg |= 0xC;
+ emi_val = 1;
+ } else {
+ /* Roll back the default values */
+ tipg_reg |= 0x08;
+ emi_val = 1;
+ }
- if (hw->mac.type == e1000_pch2lan)
- emi_addr = I82579_RX_CONFIG;
+ E1000_WRITE_REG(hw, E1000_TIPG, tipg_reg);
+
+ ret_val = hw->phy.ops.acquire(hw);
+ if (ret_val)
+ return ret_val;
+
+ if (hw->mac.type == e1000_pch2lan)
+ emi_addr = I82579_RX_CONFIG;
+ else
+ emi_addr = I217_RX_CONFIG;
+ ret_val = e1000_write_emi_reg_locked(hw, emi_addr, emi_val);
+
+ if (hw->mac.type == e1000_pch_lpt ||
+ hw->mac.type == e1000_pch_spt) {
+ u16 phy_reg;
+
+ hw->phy.ops.read_reg_locked(hw, I217_PLL_CLOCK_GATE_REG,
+ &phy_reg);
+ phy_reg &= ~I217_PLL_CLOCK_GATE_MASK;
+ if (speed == SPEED_100 || speed == SPEED_10)
+ phy_reg |= 0x3E8;
else
- emi_addr = I217_RX_CONFIG;
- ret_val = e1000_write_emi_reg_locked(hw, emi_addr, 0);
+ phy_reg |= 0xFA;
+ hw->phy.ops.write_reg_locked(hw,
+ I217_PLL_CLOCK_GATE_REG,
+ phy_reg);
+ }
+ hw->phy.ops.release(hw);
+
+ if (ret_val)
+ return ret_val;
- hw->phy.ops.release(hw);
+ if (hw->mac.type == e1000_pch_spt) {
+ u16 data;
+ u16 ptr_gap;
+
+ if (speed == SPEED_1000) {
+ ret_val = hw->phy.ops.acquire(hw);
+ if (ret_val)
+ return ret_val;
+
+ ret_val = hw->phy.ops.read_reg_locked(hw,
+ PHY_REG(776, 20),
+ &data);
+ if (ret_val) {
+ hw->phy.ops.release(hw);
+ return ret_val;
+ }
+
+ ptr_gap = (data & (0x3FF << 2)) >> 2;
+ if (ptr_gap < 0x18) {
+ data &= ~(0x3FF << 2);
+ data |= (0x18 << 2);
+ ret_val =
+ hw->phy.ops.write_reg_locked(hw,
+ PHY_REG(776, 20), data);
+ }
+ hw->phy.ops.release(hw);
+ if (ret_val)
+ return ret_val;
+ } else {
+ ret_val = hw->phy.ops.acquire(hw);
+ if (ret_val)
+ return ret_val;
+
+ ret_val = hw->phy.ops.write_reg_locked(hw,
+ PHY_REG(776, 20),
+ 0xC023);
+ hw->phy.ops.release(hw);
+ if (ret_val)
+ return ret_val;
- if (ret_val)
- return ret_val;
+ }
}
}
+ /* I217 Packet Loss issue:
+ * ensure that FEXTNVM4 Beacon Duration is set correctly
+ * on power up.
+ * Set the Beacon Duration for I217 to 8 usec
+ */
+ if ((hw->mac.type == e1000_pch_lpt) ||
+ (hw->mac.type == e1000_pch_spt)) {
+ u32 mac_reg;
+
+ mac_reg = E1000_READ_REG(hw, E1000_FEXTNVM4);
+ mac_reg &= ~E1000_FEXTNVM4_BEACON_DURATION_MASK;
+ mac_reg |= E1000_FEXTNVM4_BEACON_DURATION_8USEC;
+ E1000_WRITE_REG(hw, E1000_FEXTNVM4, mac_reg);
+ }
+
/* Work-around I218 hang issue */
if ((hw->device_id == E1000_DEV_ID_PCH_LPTLP_I218_LM) ||
(hw->device_id == E1000_DEV_ID_PCH_LPTLP_I218_V) ||
@@ -1530,7 +1699,8 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
if (ret_val)
return ret_val;
}
- if (hw->mac.type == e1000_pch_lpt) {
+ if ((hw->mac.type == e1000_pch_lpt) ||
+ (hw->mac.type == e1000_pch_spt)) {
/* Set platform power management values for
* Latency Tolerance Reporting (LTR)
* Optimized Buffer Flush/Fill (OBFF)
@@ -1543,6 +1713,19 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
/* Clear link partner's EEE ability */
hw->dev_spec.ich8lan.eee_lp_ability = 0;
+ /* FEXTNVM6 K1-off workaround */
+ if (hw->mac.type == e1000_pch_spt) {
+ u32 pcieanacfg = E1000_READ_REG(hw, E1000_PCIEANACFG);
+ u32 fextnvm6 = E1000_READ_REG(hw, E1000_FEXTNVM6);
+
+ if (pcieanacfg & E1000_FEXTNVM6_K1_OFF_ENABLE)
+ fextnvm6 |= E1000_FEXTNVM6_K1_OFF_ENABLE;
+ else
+ fextnvm6 &= ~E1000_FEXTNVM6_K1_OFF_ENABLE;
+
+ E1000_WRITE_REG(hw, E1000_FEXTNVM6, fextnvm6);
+ }
+
if (!link)
return E1000_SUCCESS; /* No link detected */
@@ -1636,6 +1819,7 @@ void e1000_init_function_pointers_ich8lan(struct e1000_hw *hw)
case e1000_pchlan:
case e1000_pch2lan:
case e1000_pch_lpt:
+ case e1000_pch_spt:
hw->phy.ops.init_params = e1000_init_phy_params_pchlan;
break;
default:
@@ -2018,7 +2202,7 @@ static s32 e1000_check_reset_block_ich8lan(struct e1000_hw *hw)
continue;
}
blocked = FALSE;
- } while (blocked && (i++ < 10));
+ } while (blocked && (i++ < 30));
return blocked ? E1000_BLK_PHY_RESET : E1000_SUCCESS;
}
@@ -2099,6 +2283,7 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw)
case e1000_pchlan:
case e1000_pch2lan:
case e1000_pch_lpt:
+ case e1000_pch_spt:
sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG_ICH8M;
break;
default:
@@ -2989,7 +3174,6 @@ static s32 e1000_set_lplu_state_pchlan(struct e1000_hw *hw, bool active)
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)
return ret_val;
@@ -3209,12 +3393,47 @@ static s32 e1000_valid_nvm_bank_detect_ich8lan(struct e1000_hw *hw, u32 *bank)
struct e1000_nvm_info *nvm = &hw->nvm;
u32 bank1_offset = nvm->flash_bank_size * sizeof(u16);
u32 act_offset = E1000_ICH_NVM_SIG_WORD * 2 + 1;
+ u32 nvm_dword = 0;
u8 sig_byte = 0;
s32 ret_val;
DEBUGFUNC("e1000_valid_nvm_bank_detect_ich8lan");
switch (hw->mac.type) {
+ case e1000_pch_spt:
+ bank1_offset = nvm->flash_bank_size;
+ act_offset = E1000_ICH_NVM_SIG_WORD;
+
+ /* set bank to 0 in case flash read fails */
+ *bank = 0;
+
+ /* Check bank 0 */
+ ret_val = e1000_read_flash_dword_ich8lan(hw, act_offset,
+ &nvm_dword);
+ if (ret_val)
+ return ret_val;
+ sig_byte = (u8)((nvm_dword & 0xFF00) >> 8);
+ if ((sig_byte & E1000_ICH_NVM_VALID_SIG_MASK) ==
+ E1000_ICH_NVM_SIG_VALUE) {
+ *bank = 0;
+ return E1000_SUCCESS;
+ }
+
+ /* Check bank 1 */
+ ret_val = e1000_read_flash_dword_ich8lan(hw, act_offset +
+ bank1_offset,
+ &nvm_dword);
+ if (ret_val)
+ return ret_val;
+ sig_byte = (u8)((nvm_dword & 0xFF00) >> 8);
+ if ((sig_byte & E1000_ICH_NVM_VALID_SIG_MASK) ==
+ E1000_ICH_NVM_SIG_VALUE) {
+ *bank = 1;
+ return E1000_SUCCESS;
+ }
+
+ DEBUGOUT("ERROR: No valid NVM bank present\n");
+ return -E1000_ERR_NVM;
case e1000_ich8lan:
case e1000_ich9lan:
eecd = E1000_READ_REG(hw, E1000_EECD);
@@ -3262,6 +3481,99 @@ static s32 e1000_valid_nvm_bank_detect_ich8lan(struct e1000_hw *hw, u32 *bank)
}
/**
+ * e1000_read_nvm_spt - NVM access for SPT
+ * @hw: pointer to the HW structure
+ * @offset: The offset (in bytes) of the word(s) to read.
+ * @words: Size of data to read in words.
+ * @data: pointer to the word(s) to read at offset.
+ *
+ * Reads a word(s) from the NVM
+ **/
+static s32 e1000_read_nvm_spt(struct e1000_hw *hw, u16 offset, u16 words,
+ u16 *data)
+{
+ struct e1000_nvm_info *nvm = &hw->nvm;
+ struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
+ u32 act_offset;
+ s32 ret_val = E1000_SUCCESS;
+ u32 bank = 0;
+ u32 dword = 0;
+ u16 offset_to_read;
+ u16 i;
+
+ DEBUGFUNC("e1000_read_nvm_spt");
+
+ if ((offset >= nvm->word_size) || (words > nvm->word_size - offset) ||
+ (words == 0)) {
+ DEBUGOUT("nvm parameter(s) out of bounds\n");
+ ret_val = -E1000_ERR_NVM;
+ goto out;
+ }
+
+ nvm->ops.acquire(hw);
+
+ ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank);
+ if (ret_val != E1000_SUCCESS) {
+ DEBUGOUT("Could not detect valid bank, assuming bank 0\n");
+ bank = 0;
+ }
+
+ act_offset = (bank) ? nvm->flash_bank_size : 0;
+ act_offset += offset;
+
+ ret_val = E1000_SUCCESS;
+
+ for (i = 0; i < words; i += 2) {
+ if (words - i == 1) {
+ if (dev_spec->shadow_ram[offset+i].modified) {
+ data[i] = dev_spec->shadow_ram[offset+i].value;
+ } else {
+ offset_to_read = act_offset + i -
+ ((act_offset + i) % 2);
+ ret_val =
+ e1000_read_flash_dword_ich8lan(hw,
+ offset_to_read,
+ &dword);
+ if (ret_val)
+ break;
+ if ((act_offset + i) % 2 == 0)
+ data[i] = (u16)(dword & 0xFFFF);
+ else
+ data[i] = (u16)((dword >> 16) & 0xFFFF);
+ }
+ } else {
+ offset_to_read = act_offset + i;
+ if (!(dev_spec->shadow_ram[offset+i].modified) ||
+ !(dev_spec->shadow_ram[offset+i+1].modified)) {
+ ret_val =
+ e1000_read_flash_dword_ich8lan(hw,
+ offset_to_read,
+ &dword);
+ if (ret_val)
+ break;
+ }
+ if (dev_spec->shadow_ram[offset+i].modified)
+ data[i] = dev_spec->shadow_ram[offset+i].value;
+ else
+ data[i] = (u16) (dword & 0xFFFF);
+ if (dev_spec->shadow_ram[offset+i].modified)
+ data[i+1] =
+ dev_spec->shadow_ram[offset+i+1].value;
+ else
+ data[i+1] = (u16) (dword >> 16 & 0xFFFF);
+ }
+ }
+
+ nvm->ops.release(hw);
+
+out:
+ if (ret_val)
+ DEBUGOUT1("NVM read error: %d\n", ret_val);
+
+ return ret_val;
+}
+
+/**
* e1000_read_nvm_ich8lan - Read word(s) from the NVM
* @hw: pointer to the HW structure
* @offset: The offset (in bytes) of the word(s) to read.
@@ -3348,7 +3660,11 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw)
/* Clear FCERR and DAEL in hw status by writing 1 */
hsfsts.hsf_status.flcerr = 1;
hsfsts.hsf_status.dael = 1;
- E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFSTS, hsfsts.regval);
+ if (hw->mac.type == e1000_pch_spt)
+ E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS,
+ hsfsts.regval & 0xFFFF);
+ else
+ E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFSTS, hsfsts.regval);
/* Either we should have a hardware SPI cycle in progress
* bit to check against, in order to start a new cycle or
@@ -3364,7 +3680,12 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw)
* Begin by setting Flash Cycle Done.
*/
hsfsts.hsf_status.flcdone = 1;
- E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFSTS, hsfsts.regval);
+ if (hw->mac.type == e1000_pch_spt)
+ E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS,
+ hsfsts.regval & 0xFFFF);
+ else
+ E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFSTS,
+ hsfsts.regval);
ret_val = E1000_SUCCESS;
} else {
s32 i;
@@ -3386,8 +3707,12 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw)
* now set the Flash Cycle Done.
*/
hsfsts.hsf_status.flcdone = 1;
- E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFSTS,
- hsfsts.regval);
+ if (hw->mac.type == e1000_pch_spt)
+ E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS,
+ hsfsts.regval & 0xFFFF);
+ else
+ E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFSTS,
+ hsfsts.regval);
} else {
DEBUGOUT("Flash controller busy, cannot get access\n");
}
@@ -3412,10 +3737,17 @@ static s32 e1000_flash_cycle_ich8lan(struct e1000_hw *hw, u32 timeout)
DEBUGFUNC("e1000_flash_cycle_ich8lan");
/* Start a cycle by writing 1 in Flash Cycle Go in Hw Flash Control */
- hsflctl.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFCTL);
+ if (hw->mac.type == e1000_pch_spt)
+ hsflctl.regval = E1000_READ_FLASH_REG(hw, ICH_FLASH_HSFSTS)>>16;
+ else
+ hsflctl.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFCTL);
hsflctl.hsf_ctrl.flcgo = 1;
- E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL, hsflctl.regval);
+ if (hw->mac.type == e1000_pch_spt)
+ E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS,
+ hsflctl.regval << 16);
+ else
+ E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL, hsflctl.regval);
/* wait till FDONE bit is set to 1 */
do {
@@ -3432,6 +3764,29 @@ static s32 e1000_flash_cycle_ich8lan(struct e1000_hw *hw, u32 timeout)
}
/**
+ * e1000_read_flash_dword_ich8lan - Read dword from flash
+ * @hw: pointer to the HW structure
+ * @offset: offset to data location
+ * @data: pointer to the location for storing the data
+ *
+ * Reads the flash dword at offset into data. Offset is converted
+ * to bytes before read.
+ **/
+static s32 e1000_read_flash_dword_ich8lan(struct e1000_hw *hw, u32 offset,
+ u32 *data)
+{
+ DEBUGFUNC("e1000_read_flash_dword_ich8lan");
+
+ if (!data)
+ return -E1000_ERR_NVM;
+
+ /* Must convert word offset into bytes. */
+ offset <<= 1;
+
+ return e1000_read_flash_data32_ich8lan(hw, offset, data);
+}
+
+/**
* e1000_read_flash_word_ich8lan - Read word from flash
* @hw: pointer to the HW structure
* @offset: offset to data location
@@ -3468,7 +3823,13 @@ static s32 e1000_read_flash_byte_ich8lan(struct e1000_hw *hw, u32 offset,
s32 ret_val;
u16 word = 0;
- ret_val = e1000_read_flash_data_ich8lan(hw, offset, 1, &word);
+ /* In SPT, only 32 bits access is supported,
+ * so this function should not be called.
+ */
+ if (hw->mac.type == e1000_pch_spt)
+ return -E1000_ERR_NVM;
+ else
+ ret_val = e1000_read_flash_data_ich8lan(hw, offset, 1, &word);
if (ret_val)
return ret_val;
@@ -3554,6 +3915,83 @@ static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
return ret_val;
}
+/**
+ * e1000_read_flash_data32_ich8lan - Read dword from NVM
+ * @hw: pointer to the HW structure
+ * @offset: The offset (in bytes) of the dword to read.
+ * @data: Pointer to the dword to store the value read.
+ *
+ * Reads a byte or word from the NVM using the flash access registers.
+ **/
+static s32 e1000_read_flash_data32_ich8lan(struct e1000_hw *hw, u32 offset,
+ u32 *data)
+{
+ union ich8_hws_flash_status hsfsts;
+ union ich8_hws_flash_ctrl hsflctl;
+ u32 flash_linear_addr;
+ s32 ret_val = -E1000_ERR_NVM;
+ u8 count = 0;
+
+ DEBUGFUNC("e1000_read_flash_data_ich8lan");
+
+ if (offset > ICH_FLASH_LINEAR_ADDR_MASK ||
+ hw->mac.type != e1000_pch_spt)
+ return -E1000_ERR_NVM;
+ flash_linear_addr = ((ICH_FLASH_LINEAR_ADDR_MASK & offset) +
+ hw->nvm.flash_base_addr);
+
+ do {
+ usec_delay(1);
+ /* Steps */
+ ret_val = e1000_flash_cycle_init_ich8lan(hw);
+ if (ret_val != E1000_SUCCESS)
+ break;
+ /* In SPT, This register is in Lan memory space, not flash.
+ * Therefore, only 32 bit access is supported
+ */
+ hsflctl.regval = E1000_READ_FLASH_REG(hw, ICH_FLASH_HSFSTS)>>16;
+
+ /* 0b/1b corresponds to 1 or 2 byte size, respectively. */
+ hsflctl.hsf_ctrl.fldbcount = sizeof(u32) - 1;
+ hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_READ;
+ /* In SPT, This register is in Lan memory space, not flash.
+ * Therefore, only 32 bit access is supported
+ */
+ E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS,
+ (u32)hsflctl.regval << 16);
+ E1000_WRITE_FLASH_REG(hw, ICH_FLASH_FADDR, flash_linear_addr);
+
+ ret_val = e1000_flash_cycle_ich8lan(hw,
+ ICH_FLASH_READ_COMMAND_TIMEOUT);
+
+ /* Check if FCERR is set to 1, if set to 1, clear it
+ * and try the whole sequence a few more times, else
+ * read in (shift in) the Flash Data0, the order is
+ * least significant byte first msb to lsb
+ */
+ if (ret_val == E1000_SUCCESS) {
+ *data = E1000_READ_FLASH_REG(hw, ICH_FLASH_FDATA0);
+ break;
+ } else {
+ /* If we've gotten here, then things are probably
+ * completely hosed, but if the error condition is
+ * detected, it won't hurt to give it another try...
+ * ICH_FLASH_CYCLE_REPEAT_COUNT times.
+ */
+ hsfsts.regval = E1000_READ_FLASH_REG16(hw,
+ ICH_FLASH_HSFSTS);
+ if (hsfsts.hsf_status.flcerr) {
+ /* Repeat for some time before giving up. */
+ continue;
+ } else if (!hsfsts.hsf_status.flcdone) {
+ DEBUGOUT("Timeout error - flash cycle did not complete.\n");
+ break;
+ }
+ }
+ } while (count++ < ICH_FLASH_CYCLE_REPEAT_COUNT);
+
+ return ret_val;
+}
/**
* e1000_write_nvm_ich8lan - Write word(s) to the NVM
@@ -3592,6 +4030,175 @@ static s32 e1000_write_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words,
}
/**
+ * e1000_update_nvm_checksum_spt - Update the checksum for NVM
+ * @hw: pointer to the HW structure
+ *
+ * The NVM checksum is updated by calling the generic update_nvm_checksum,
+ * which writes the checksum to the shadow ram. The changes in the shadow
+ * ram are then committed to the EEPROM by processing each bank at a time
+ * checking for the modified bit and writing only the pending changes.
+ * After a successful commit, the shadow ram is cleared and is ready for
+ * future writes.
+ **/
+static s32 e1000_update_nvm_checksum_spt(struct e1000_hw *hw)
+{
+ struct e1000_nvm_info *nvm = &hw->nvm;
+ struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
+ u32 i, act_offset, new_bank_offset, old_bank_offset, bank;
+ s32 ret_val;
+ u32 dword = 0;
+
+ DEBUGFUNC("e1000_update_nvm_checksum_spt");
+
+ ret_val = e1000_update_nvm_checksum_generic(hw);
+ if (ret_val)
+ goto out;
+
+ if (nvm->type != e1000_nvm_flash_sw)
+ goto out;
+
+ nvm->ops.acquire(hw);
+
+ /* We're writing to the opposite bank so if we're on bank 1,
+ * write to bank 0 etc. We also need to erase the segment that
+ * is going to be written
+ */
+ ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank);
+ if (ret_val != E1000_SUCCESS) {
+ DEBUGOUT("Could not detect valid bank, assuming bank 0\n");
+ bank = 0;
+ }
+
+ if (bank == 0) {
+ new_bank_offset = nvm->flash_bank_size;
+ old_bank_offset = 0;
+ ret_val = e1000_erase_flash_bank_ich8lan(hw, 1);
+ if (ret_val)
+ goto release;
+ } else {
+ old_bank_offset = nvm->flash_bank_size;
+ new_bank_offset = 0;
+ ret_val = e1000_erase_flash_bank_ich8lan(hw, 0);
+ if (ret_val)
+ goto release;
+ }
+ for (i = 0; i < E1000_SHADOW_RAM_WORDS; i += 2) {
+ /* Determine whether to write the value stored
+ * in the other NVM bank or a modified value stored
+ * in the shadow RAM
+ */
+ ret_val = e1000_read_flash_dword_ich8lan(hw,
+ i + old_bank_offset,
+ &dword);
+
+ if (dev_spec->shadow_ram[i].modified) {
+ dword &= 0xffff0000;
+ dword |= (dev_spec->shadow_ram[i].value & 0xffff);
+ }
+ if (dev_spec->shadow_ram[i + 1].modified) {
+ dword &= 0x0000ffff;
+ dword |= ((dev_spec->shadow_ram[i + 1].value & 0xffff)
+ << 16);
+ }
+ if (ret_val)
+ break;
+
+ /* If the word is 0x13, then make sure the signature bits
+ * (15:14) are 11b until the commit has completed.
+ * This will allow us to write 10b which indicates the
+ * signature is valid. We want to do this after the write
+ * has completed so that we don't mark the segment valid
+ * while the write is still in progress
+ */
+ if (i == E1000_ICH_NVM_SIG_WORD - 1)
+ dword |= E1000_ICH_NVM_SIG_MASK << 16;
+
+ /* Convert offset to bytes. */
+ act_offset = (i + new_bank_offset) << 1;
+
+ usec_delay(100);
+
+ /* Write the data to the new bank. Offset in words*/
+ act_offset = i + new_bank_offset;
+ ret_val = e1000_retry_write_flash_dword_ich8lan(hw, act_offset,
+ dword);
+ if (ret_val)
+ break;
+ }
+
+ /* Don't bother writing the segment valid bits if sector
+ * programming failed.
+ */
+ if (ret_val) {
+ DEBUGOUT("Flash commit failed.\n");
+ goto release;
+ }
+
+ /* Finally validate the new segment by setting bit 15:14
+ * to 10b in word 0x13 , this can be done without an
+ * erase as well since these bits are 11 to start with
+ * and we need to change bit 14 to 0b
+ */
+ act_offset = new_bank_offset + E1000_ICH_NVM_SIG_WORD;
+
+ /*offset in words but we read dword*/
+ --act_offset;
+ ret_val = e1000_read_flash_dword_ich8lan(hw, act_offset, &dword);
+
+ if (ret_val)
+ goto release;
+
+ dword &= 0xBFFFFFFF;
+ ret_val = e1000_retry_write_flash_dword_ich8lan(hw, act_offset, dword);
+
+ if (ret_val)
+ goto release;
+
+ /* And invalidate the previously valid segment by setting
+ * its signature word (0x13) high_byte to 0b. This can be
+ * done without an erase because flash erase sets all bits
+ * to 1's. We can write 1's to 0's without an erase
+ */
+ act_offset = (old_bank_offset + E1000_ICH_NVM_SIG_WORD) * 2 + 1;
+
+ /* offset in words but we read dword*/
+ act_offset = old_bank_offset + E1000_ICH_NVM_SIG_WORD - 1;
+ ret_val = e1000_read_flash_dword_ich8lan(hw, act_offset, &dword);
+
+ if (ret_val)
+ goto release;
+
+ dword &= 0x00FFFFFF;
+ ret_val = e1000_retry_write_flash_dword_ich8lan(hw, act_offset, dword);
+
+ if (ret_val)
+ goto release;
+
+ /* Great! Everything worked, we can now clear the cached entries. */
+ for (i = 0; i < E1000_SHADOW_RAM_WORDS; i++) {
+ dev_spec->shadow_ram[i].modified = FALSE;
+ dev_spec->shadow_ram[i].value = 0xFFFF;
+ }
+
+release:
+ nvm->ops.release(hw);
+
+ /* Reload the EEPROM, or else modifications will not appear
+ * until after the next adapter reset.
+ */
+ if (!ret_val) {
+ nvm->ops.reload(hw);
+ msec_delay(10);
+ }
+
+out:
+ if (ret_val)
+ DEBUGOUT1("NVM update error: %d\n", ret_val);
+
+ return ret_val;
+}
+
+/**
* e1000_update_nvm_checksum_ich8lan - Update the checksum for NVM
* @hw: pointer to the HW structure
*
@@ -3768,6 +4375,7 @@ static s32 e1000_validate_nvm_checksum_ich8lan(struct e1000_hw *hw)
*/
switch (hw->mac.type) {
case e1000_pch_lpt:
+ case e1000_pch_spt:
word = NVM_COMPAT;
valid_csum_mask = NVM_COMPAT_VALID_CSUM;
break;
@@ -3815,8 +4423,13 @@ static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
DEBUGFUNC("e1000_write_ich8_data");
- if (size < 1 || size > 2 || offset > ICH_FLASH_LINEAR_ADDR_MASK)
- return -E1000_ERR_NVM;
+ if (hw->mac.type == e1000_pch_spt) {
+ if (size != 4 || offset > ICH_FLASH_LINEAR_ADDR_MASK)
+ return -E1000_ERR_NVM;
+ } else {
+ if (size < 1 || size > 2 || offset > ICH_FLASH_LINEAR_ADDR_MASK)
+ return -E1000_ERR_NVM;
+ }
flash_linear_addr = ((ICH_FLASH_LINEAR_ADDR_MASK & offset) +
hw->nvm.flash_base_addr);
@@ -3827,12 +4440,29 @@ static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
ret_val = e1000_flash_cycle_init_ich8lan(hw);
if (ret_val != E1000_SUCCESS)
break;
- hsflctl.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFCTL);
+ /* In SPT, This register is in Lan memory space, not
+ * flash. Therefore, only 32 bit access is supported
+ */
+ if (hw->mac.type == e1000_pch_spt)
+ hsflctl.regval =
+ E1000_READ_FLASH_REG(hw, ICH_FLASH_HSFSTS)>>16;
+ else
+ hsflctl.regval =
+ E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFCTL);
/* 0b/1b corresponds to 1 or 2 byte size, respectively. */
hsflctl.hsf_ctrl.fldbcount = size - 1;
hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_WRITE;
- E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL, hsflctl.regval);
+ /* In SPT, This register is in Lan memory space,
+ * not flash. Therefore, only 32 bit access is
+ * supported
+ */
+ if (hw->mac.type == e1000_pch_spt)
+ E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS,
+ hsflctl.regval << 16);
+ else
+ E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL,
+ hsflctl.regval);
E1000_WRITE_FLASH_REG(hw, ICH_FLASH_FADDR, flash_linear_addr);
@@ -3870,6 +4500,94 @@ static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
return ret_val;
}
+/**
+* e1000_write_flash_data32_ich8lan - Writes 4 bytes to the NVM
+* @hw: pointer to the HW structure
+* @offset: The offset (in bytes) of the dwords to read.
+* @data: The 4 bytes to write to the NVM.
+*
+* Writes one/two/four bytes to the NVM using the flash access registers.
+**/
+static s32 e1000_write_flash_data32_ich8lan(struct e1000_hw *hw, u32 offset,
+ u32 data)
+{
+ union ich8_hws_flash_status hsfsts;
+ union ich8_hws_flash_ctrl hsflctl;
+ u32 flash_linear_addr;
+ s32 ret_val;
+ u8 count = 0;
+
+ DEBUGFUNC("e1000_write_flash_data32_ich8lan");
+
+ if (hw->mac.type == e1000_pch_spt) {
+ if (offset > ICH_FLASH_LINEAR_ADDR_MASK)
+ return -E1000_ERR_NVM;
+ }
+ flash_linear_addr = ((ICH_FLASH_LINEAR_ADDR_MASK & offset) +
+ hw->nvm.flash_base_addr);
+ do {
+ usec_delay(1);
+ /* Steps */
+ ret_val = e1000_flash_cycle_init_ich8lan(hw);
+ if (ret_val != E1000_SUCCESS)
+ break;
+
+ /* In SPT, This register is in Lan memory space, not
+ * flash. Therefore, only 32 bit access is supported
+ */
+ if (hw->mac.type == e1000_pch_spt)
+ hsflctl.regval = E1000_READ_FLASH_REG(hw,
+ ICH_FLASH_HSFSTS)
+ >> 16;
+ else
+ hsflctl.regval = E1000_READ_FLASH_REG16(hw,
+ ICH_FLASH_HSFCTL);
+
+ hsflctl.hsf_ctrl.fldbcount = sizeof(u32) - 1;
+ hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_WRITE;
+
+ /* In SPT, This register is in Lan memory space,
+ * not flash. Therefore, only 32 bit access is
+ * supported
+ */
+ if (hw->mac.type == e1000_pch_spt)
+ E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS,
+ hsflctl.regval << 16);
+ else
+ E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL,
+ hsflctl.regval);
+
+ E1000_WRITE_FLASH_REG(hw, ICH_FLASH_FADDR, flash_linear_addr);
+
+ E1000_WRITE_FLASH_REG(hw, ICH_FLASH_FDATA0, data);
+
+ /* check if FCERR is set to 1 , if set to 1, clear it
+ * and try the whole sequence a few more times else done
+ */
+ ret_val = e1000_flash_cycle_ich8lan(hw,
+ ICH_FLASH_WRITE_COMMAND_TIMEOUT);
+
+ if (ret_val == E1000_SUCCESS)
+ break;
+
+ /* If we're here, then things are most likely
+ * completely hosed, but if the error condition
+ * is detected, it won't hurt to give it another
+ * try...ICH_FLASH_CYCLE_REPEAT_COUNT times.
+ */
+ hsfsts.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFSTS);
+
+ if (hsfsts.hsf_status.flcerr)
+ /* Repeat for some time before giving up. */
+ continue;
+ if (!hsfsts.hsf_status.flcdone) {
+ DEBUGOUT("Timeout error - flash cycle did not complete.\n");
+ break;
+ }
+ } while (count++ < ICH_FLASH_CYCLE_REPEAT_COUNT);
+
+ return ret_val;
+}
/**
* e1000_write_flash_byte_ich8lan - Write a single byte to NVM
@@ -3889,7 +4607,42 @@ static s32 e1000_write_flash_byte_ich8lan(struct e1000_hw *hw, u32 offset,
return e1000_write_flash_data_ich8lan(hw, offset, 1, word);
}
+/**
+* e1000_retry_write_flash_dword_ich8lan - Writes a dword to NVM
+* @hw: pointer to the HW structure
+* @offset: The offset of the word to write.
+* @dword: The dword to write to the NVM.
+*
+* Writes a single dword to the NVM using the flash access registers.
+* Goes through a retry algorithm before giving up.
+**/
+static s32 e1000_retry_write_flash_dword_ich8lan(struct e1000_hw *hw,
+ u32 offset, u32 dword)
+{
+ s32 ret_val;
+ u16 program_retries;
+ DEBUGFUNC("e1000_retry_write_flash_dword_ich8lan");
+
+ /* Must convert word offset into bytes. */
+ offset <<= 1;
+
+ ret_val = e1000_write_flash_data32_ich8lan(hw, offset, dword);
+
+ if (!ret_val)
+ return ret_val;
+ for (program_retries = 0; program_retries < 100; program_retries++) {
+ DEBUGOUT2("Retrying Byte %8.8X at offset %u\n", dword, offset);
+ usec_delay(100);
+ ret_val = e1000_write_flash_data32_ich8lan(hw, offset, dword);
+ if (ret_val == E1000_SUCCESS)
+ break;
+ }
+ if (program_retries == 100)
+ return -E1000_ERR_NVM;
+
+ return E1000_SUCCESS;
+}
/**
* e1000_retry_write_flash_byte_ich8lan - Writes a single byte to NVM
@@ -3999,12 +4752,22 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank)
/* Write a value 11 (block Erase) in Flash
* Cycle field in hw flash control
*/
- hsflctl.regval =
- E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFCTL);
+ if (hw->mac.type == e1000_pch_spt)
+ hsflctl.regval =
+ E1000_READ_FLASH_REG(hw,
+ ICH_FLASH_HSFSTS)>>16;
+ else
+ hsflctl.regval =
+ E1000_READ_FLASH_REG16(hw,
+ ICH_FLASH_HSFCTL);
hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_ERASE;
- E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL,
- hsflctl.regval);
+ if (hw->mac.type == e1000_pch_spt)
+ E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS,
+ hsflctl.regval << 16);
+ else
+ E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL,
+ hsflctl.regval);
/* Write the last 24 bits of an index within the
* block into Flash Linear address field in Flash
@@ -4437,7 +5200,8 @@ static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw)
E1000_WRITE_REG(hw, E1000_RFCTL, reg);
/* Enable ECC on Lynxpoint */
- if (hw->mac.type == e1000_pch_lpt) {
+ if ((hw->mac.type == e1000_pch_lpt) ||
+ (hw->mac.type == e1000_pch_spt)) {
reg = E1000_READ_REG(hw, E1000_PBECCSTS);
reg |= E1000_PBECCSTS_ECC_ENABLE;
E1000_WRITE_REG(hw, E1000_PBECCSTS, reg);
@@ -4869,7 +5633,8 @@ void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw)
if ((device_id == E1000_DEV_ID_PCH_LPTLP_I218_LM) ||
(device_id == E1000_DEV_ID_PCH_LPTLP_I218_V) ||
(device_id == E1000_DEV_ID_PCH_I218_LM3) ||
- (device_id == E1000_DEV_ID_PCH_I218_V3)) {
+ (device_id == E1000_DEV_ID_PCH_I218_V3) ||
+ (hw->mac.type == e1000_pch_spt)) {
u32 fextnvm6 = E1000_READ_REG(hw, E1000_FEXTNVM6);
E1000_WRITE_REG(hw, E1000_FEXTNVM6,
@@ -4985,19 +5750,18 @@ out:
* the PHY.
* On i217, setup Intel Rapid Start Technology.
**/
-void e1000_resume_workarounds_pchlan(struct e1000_hw *hw)
+u32 e1000_resume_workarounds_pchlan(struct e1000_hw *hw)
{
s32 ret_val;
DEBUGFUNC("e1000_resume_workarounds_pchlan");
-
if (hw->mac.type < e1000_pch2lan)
- return;
+ return E1000_SUCCESS;
ret_val = e1000_init_phy_workarounds_pchlan(hw);
if (ret_val) {
DEBUGOUT1("Failed to init PHY flow ret_val=%d\n", ret_val);
- return;
+ return ret_val;
}
/* For i217 Intel Rapid Start Technology support when the system
@@ -5011,7 +5775,7 @@ void e1000_resume_workarounds_pchlan(struct e1000_hw *hw)
ret_val = hw->phy.ops.acquire(hw);
if (ret_val) {
DEBUGOUT("Failed to setup iRST\n");
- return;
+ return ret_val;
}
/* Clear Auto Enable LPI after link up */
@@ -5045,7 +5809,9 @@ release:
if (ret_val)
DEBUGOUT1("Error %d in resume workarounds\n", ret_val);
hw->phy.ops.release(hw);
+ return ret_val;
}
+ return E1000_SUCCESS;
}
/**
@@ -5233,11 +5999,10 @@ static s32 e1000_get_cfg_done_ich8lan(struct e1000_hw *hw)
/* Clear PHY Reset Asserted bit */
status = E1000_READ_REG(hw, E1000_STATUS);
- if (status & E1000_STATUS_PHYRA) {
+ if (status & E1000_STATUS_PHYRA)
E1000_WRITE_REG(hw, E1000_STATUS, status & ~E1000_STATUS_PHYRA);
- } else {
+ else
DEBUGOUT("PHY Reset Asserted not set - needs delay\n");
- }
/* If EEPROM is not marked present, init the IGP 3 PHY manually */
if (hw->mac.type <= e1000_ich9lan) {
diff --git a/usr/src/uts/common/io/e1000api/e1000_ich8lan.h b/usr/src/uts/common/io/e1000api/e1000_ich8lan.h
index 999e856be3..cc76b01ff0 100644
--- a/usr/src/uts/common/io/e1000api/e1000_ich8lan.h
+++ b/usr/src/uts/common/io/e1000api/e1000_ich8lan.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2014, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -86,7 +86,7 @@
(ID_LED_DEF1_DEF2))
#define E1000_ICH_NVM_SIG_WORD 0x13
-#define E1000_ICH_NVM_SIG_MASK 0xC000
+#define E1000_ICH_NVM_SIG_MASK 0xC000UL
#define E1000_ICH_NVM_VALID_SIG_MASK 0xC0
#define E1000_ICH_NVM_SIG_VALUE 0x80
@@ -107,9 +107,23 @@
#define E1000_FEXTNVM6_REQ_PLL_CLK 0x00000100
#define E1000_FEXTNVM6_ENABLE_K1_ENTRY_CONDITION 0x00000200
-
+#define E1000_FEXTNVM6_K1_OFF_ENABLE 0x80000000
+/* bit for disabling packet buffer read */
+#define E1000_FEXTNVM7_DISABLE_PB_READ 0x00040000
+#define E1000_FEXTNVM7_SIDE_CLK_UNGATE 0x00000004
#define E1000_FEXTNVM7_DISABLE_SMB_PERST 0x00000020
-
+#define E1000_FEXTNVM9_IOSFSB_CLKGATE_DIS 0x00000800
+#define E1000_FEXTNVM9_IOSFSB_CLKREQ_DIS 0x00001000
+#define E1000_FEXTNVM11_DISABLE_PB_READ 0x00000200
+#define E1000_FEXTNVM11_DISABLE_MULR_FIX 0x00002000
+
+/* bit24: RXDCTL thresholds granularity: 0 - cache lines, 1 - descriptors */
+#define E1000_RXDCTL_THRESH_UNIT_DESC 0x01000000
+
+#define NVM_SIZE_MULTIPLIER 4096 /*multiplier for NVMS field*/
+#define E1000_FLASH_BASE_ADDR 0xE000 /*offset of NVM access regs*/
+#define E1000_CTRL_EXT_NVMVS 0x3 /*NVM valid sector */
+#define E1000_TARC0_CB_MULTIQ_3_REQ (1 << 28 | 1 << 29)
#define PCIE_ICH8_SNOOP_ALL PCIE_NO_SNOOP_ALL
#define E1000_ICH_RAR_ENTRIES 7
@@ -171,6 +185,8 @@
#define E1000_NVM_K1_CONFIG 0x1B /* NVM K1 Config Word */
#define E1000_NVM_K1_ENABLE 0x1 /* NVM Enable K1 bit */
+#define K1_ENTRY_LATENCY 0
+#define K1_MIN_TIME 1
/* SMBus Control Phy Register */
#define CV_SMB_CTRL PHY_REG(769, 23)
@@ -184,6 +200,10 @@
#define I218_ULP_CONFIG1_INBAND_EXIT 0x0020 /* Inband on ULP exit */
#define I218_ULP_CONFIG1_WOL_HOST 0x0040 /* WoL Host on ULP exit */
#define I218_ULP_CONFIG1_RESET_TO_SMBUS 0x0100 /* Reset to SMBus mode */
+/* enable ULP even if when phy powered down via lanphypc */
+#define I218_ULP_CONFIG1_EN_ULP_LANPHYPC 0x0400
+/* disable clear of sticky ULP on PERST */
+#define I218_ULP_CONFIG1_DIS_CLR_STICKY_ON_PERST 0x0800
#define I218_ULP_CONFIG1_DISABLE_SMB_PERST 0x1000 /* Disable on PERST# */
/* SMBus Address Phy Register */
@@ -222,6 +242,9 @@
#define HV_PM_CTRL_PLL_STOP_IN_K1_GIGA 0x100
#define HV_PM_CTRL_K1_ENABLE 0x4000
+#define I217_PLL_CLOCK_GATE_REG PHY_REG(772, 28)
+#define I217_PLL_CLOCK_GATE_MASK 0x07FF
+
#define SW_FLAG_TIMEOUT 1000 /* SW Semaphore flag timeout in ms */
/* Inband Control */
@@ -307,7 +330,7 @@ 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_suspend_workarounds_ich8lan(struct e1000_hw *hw);
-void e1000_resume_workarounds_pchlan(struct e1000_hw *hw);
+u32 e1000_resume_workarounds_pchlan(struct e1000_hw *hw);
s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable);
void e1000_copy_rx_addrs_to_phy_ich8lan(struct e1000_hw *hw);
s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable);
diff --git a/usr/src/uts/common/io/e1000api/e1000_mac.c b/usr/src/uts/common/io/e1000api/e1000_mac.c
index b888b341c4..1c863073f0 100644
--- a/usr/src/uts/common/io/e1000api/e1000_mac.c
+++ b/usr/src/uts/common/io/e1000api/e1000_mac.c
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2014, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/usr/src/uts/common/io/e1000api/e1000_mac.h b/usr/src/uts/common/io/e1000api/e1000_mac.h
index 2c1bfe3243..ef9789bbb5 100644
--- a/usr/src/uts/common/io/e1000api/e1000_mac.h
+++ b/usr/src/uts/common/io/e1000api/e1000_mac.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2014, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -36,9 +36,7 @@
#define _E1000_MAC_H_
void e1000_init_mac_ops_generic(struct e1000_hw *hw);
-#ifndef E1000_REMOVED
#define E1000_REMOVED(a) (0)
-#endif /* E1000_REMOVED */
void e1000_null_mac_generic(struct e1000_hw *hw);
s32 e1000_null_ops_generic(struct e1000_hw *hw);
s32 e1000_null_link_info(struct e1000_hw *hw, u16 *s, u16 *d);
diff --git a/usr/src/uts/common/io/e1000api/e1000_manage.c b/usr/src/uts/common/io/e1000api/e1000_manage.c
index 8087e656c5..f8290a22fa 100644
--- a/usr/src/uts/common/io/e1000api/e1000_manage.c
+++ b/usr/src/uts/common/io/e1000api/e1000_manage.c
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2014, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -33,7 +33,6 @@
/*$FreeBSD$*/
#include "e1000_api.h"
-
/**
* e1000_calculate_checksum - Calculate checksum for buffer
* @buffer: pointer to EEPROM
diff --git a/usr/src/uts/common/io/e1000api/e1000_manage.h b/usr/src/uts/common/io/e1000api/e1000_manage.h
index 51f176719c..303e99e321 100644
--- a/usr/src/uts/common/io/e1000api/e1000_manage.h
+++ b/usr/src/uts/common/io/e1000api/e1000_manage.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2012, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/usr/src/uts/common/io/e1000api/e1000_mbx.c b/usr/src/uts/common/io/e1000api/e1000_mbx.c
index 55477b2a6a..1de19a4df7 100644
--- a/usr/src/uts/common/io/e1000api/e1000_mbx.c
+++ b/usr/src/uts/common/io/e1000api/e1000_mbx.c
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2014, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -426,15 +426,21 @@ static s32 e1000_check_for_rst_vf(struct e1000_hw *hw,
static s32 e1000_obtain_mbx_lock_vf(struct e1000_hw *hw)
{
s32 ret_val = -E1000_ERR_MBX;
+ int count = 10;
DEBUGFUNC("e1000_obtain_mbx_lock_vf");
- /* Take ownership of the buffer */
- E1000_WRITE_REG(hw, E1000_V2PMAILBOX(0), E1000_V2PMAILBOX_VFU);
+ do {
+ /* Take ownership of the buffer */
+ E1000_WRITE_REG(hw, E1000_V2PMAILBOX(0), E1000_V2PMAILBOX_VFU);
- /* reserve mailbox for vf use */
- if (e1000_read_v2p_mailbox(hw) & E1000_V2PMAILBOX_VFU)
- ret_val = E1000_SUCCESS;
+ /* reserve mailbox for vf use */
+ if (e1000_read_v2p_mailbox(hw) & E1000_V2PMAILBOX_VFU) {
+ ret_val = E1000_SUCCESS;
+ break;
+ }
+ usec_delay(1000);
+ } while (count-- > 0);
return ret_val;
}
@@ -639,18 +645,26 @@ static s32 e1000_obtain_mbx_lock_pf(struct e1000_hw *hw, u16 vf_number)
{
s32 ret_val = -E1000_ERR_MBX;
u32 p2v_mailbox;
+ int count = 10;
DEBUGFUNC("e1000_obtain_mbx_lock_pf");
- /* Take ownership of the buffer */
- E1000_WRITE_REG(hw, E1000_P2VMAILBOX(vf_number), E1000_P2VMAILBOX_PFU);
+ do {
+ /* Take ownership of the buffer */
+ E1000_WRITE_REG(hw, E1000_P2VMAILBOX(vf_number),
+ E1000_P2VMAILBOX_PFU);
- /* reserve mailbox for vf use */
- p2v_mailbox = E1000_READ_REG(hw, E1000_P2VMAILBOX(vf_number));
- if (p2v_mailbox & E1000_P2VMAILBOX_PFU)
- ret_val = E1000_SUCCESS;
+ /* reserve mailbox for pf use */
+ p2v_mailbox = E1000_READ_REG(hw, E1000_P2VMAILBOX(vf_number));
+ if (p2v_mailbox & E1000_P2VMAILBOX_PFU) {
+ ret_val = E1000_SUCCESS;
+ break;
+ }
+ usec_delay(1000);
+ } while (count-- > 0);
return ret_val;
+
}
/**
diff --git a/usr/src/uts/common/io/e1000api/e1000_mbx.h b/usr/src/uts/common/io/e1000api/e1000_mbx.h
index d2aea5c497..fadd8494f5 100644
--- a/usr/src/uts/common/io/e1000api/e1000_mbx.h
+++ b/usr/src/uts/common/io/e1000api/e1000_mbx.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2014, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/usr/src/uts/common/io/e1000api/e1000_nvm.c b/usr/src/uts/common/io/e1000api/e1000_nvm.c
index f702f71b3a..0a1a18d4a9 100644
--- a/usr/src/uts/common/io/e1000api/e1000_nvm.c
+++ b/usr/src/uts/common/io/e1000api/e1000_nvm.c
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2014, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/usr/src/uts/common/io/e1000api/e1000_nvm.h b/usr/src/uts/common/io/e1000api/e1000_nvm.h
index 34077b2498..64a4083eb2 100644
--- a/usr/src/uts/common/io/e1000api/e1000_nvm.h
+++ b/usr/src/uts/common/io/e1000api/e1000_nvm.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2013, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -35,12 +35,10 @@
#ifndef _E1000_NVM_H_
#define _E1000_NVM_H_
-#if !defined(NO_READ_PBA_RAW) || !defined(NO_WRITE_PBA_RAW)
struct e1000_pba {
u16 word[2];
u16 *pba_block;
};
-#endif
void e1000_init_nvm_ops_generic(struct e1000_hw *hw);
diff --git a/usr/src/uts/common/io/e1000api/e1000_phy.c b/usr/src/uts/common/io/e1000api/e1000_phy.c
index f27889c83c..b2bec3e5fe 100644
--- a/usr/src/uts/common/io/e1000api/e1000_phy.c
+++ b/usr/src/uts/common/io/e1000api/e1000_phy.c
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2014, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -1827,9 +1827,9 @@ s32 e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw)
phy_data);
if (ret_val)
return ret_val;
- }
- DEBUGOUT1("M88E1000 PSCR: %X\n", phy_data);
+ DEBUGOUT1("M88E1000 PSCR: %X\n", phy_data);
+ }
ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_data);
if (ret_val)
@@ -3122,7 +3122,7 @@ s32 e1000_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data)
/* 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, FALSE);
+ FALSE, false);
goto release;
}
@@ -3286,7 +3286,7 @@ s32 e1000_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data)
/* 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, FALSE);
+ FALSE, false);
goto release;
}
@@ -3429,12 +3429,11 @@ static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset,
u16 *data, bool read, bool page_set)
{
s32 ret_val;
- u16 reg, page;
+ u16 reg = BM_PHY_REG_NUM(offset);
+ u16 page = BM_PHY_REG_PAGE(offset);
u16 phy_reg = 0;
DEBUGFUNC("e1000_access_phy_wakeup_reg_bm");
- reg = BM_PHY_REG_NUM(offset);
- page = BM_PHY_REG_PAGE(offset);
/* Gig must be disabled for MDIO accesses to Host Wakeup reg page */
if ((hw->mac.type == e1000_pchlan) &&
@@ -3544,7 +3543,6 @@ static s32 __e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data,
if (ret_val)
return ret_val;
}
-
/* 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,
@@ -3598,7 +3596,7 @@ out:
**/
s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data)
{
- return __e1000_read_phy_reg_hv(hw, offset, data, FALSE, FALSE);
+ return __e1000_read_phy_reg_hv(hw, offset, data, FALSE, false);
}
/**
@@ -3654,7 +3652,6 @@ static s32 __e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data,
if (ret_val)
return ret_val;
}
-
/* 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,
@@ -3724,7 +3721,7 @@ out:
**/
s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data)
{
- return __e1000_write_phy_reg_hv(hw, offset, data, FALSE, FALSE);
+ return __e1000_write_phy_reg_hv(hw, offset, data, FALSE, false);
}
/**
diff --git a/usr/src/uts/common/io/e1000api/e1000_phy.h b/usr/src/uts/common/io/e1000api/e1000_phy.h
index 0e5b2e6ac6..d3d563f71e 100644
--- a/usr/src/uts/common/io/e1000api/e1000_phy.h
+++ b/usr/src/uts/common/io/e1000api/e1000_phy.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2014, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/usr/src/uts/common/io/e1000api/e1000_regs.h b/usr/src/uts/common/io/e1000api/e1000_regs.h
index 5c2e3f788c..37d701722d 100644
--- a/usr/src/uts/common/io/e1000api/e1000_regs.h
+++ b/usr/src/uts/common/io/e1000api/e1000_regs.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2014, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -65,6 +65,9 @@
#define E1000_FEXTNVM4 0x00024 /* Future Extended NVM 4 - RW */
#define E1000_FEXTNVM6 0x00010 /* Future Extended NVM 6 - RW */
#define E1000_FEXTNVM7 0x000E4 /* Future Extended NVM 7 - RW */
+#define E1000_FEXTNVM9 0x5BB4 /* Future Extended NVM 9 - RW */
+#define E1000_FEXTNVM11 0x5BBC /* Future Extended NVM 11 - RW */
+#define E1000_PCIEANACFG 0x00F18 /* PCIE Analog Config */
#define E1000_FCT 0x00030 /* Flow Control Type - RW */
#define E1000_CONNSW 0x00034 /* Copper/Fiber switch control - RW */
#define E1000_VET 0x00038 /* VLAN Ether Type - RW */
@@ -107,7 +110,9 @@
#define E1000_PBA 0x01000 /* Packet Buffer Allocation - RW */
#define E1000_PBS 0x01008 /* Packet Buffer Size */
#define E1000_PBECCSTS 0x0100C /* Packet Buffer ECC Status - RW */
+#define E1000_IOSFPC 0x00F28 /* TX corrupted data */
#define E1000_EEMNGCTL 0x01010 /* MNG EEprom Control */
+#define E1000_EEMNGCTL_I210 0x01010 /* i210 MNG EEprom Mode Control */
#define E1000_EEARBC 0x01024 /* EEPROM Auto Read Bus Control */
#define E1000_EEARBC_I210 0x12024 /* EEPROM Auto Read Bus Control */
#define E1000_FLASHT 0x01028 /* FLASH Timer Register */
@@ -202,7 +207,7 @@
/* Queues fetch arbitration priority control register */
#define E1000_I210_TQAVARBCTRL 0x3574
/* Queues priority masks where _n and _p can be 0-3. */
-#define E1000_TQAVARBCTRL_QUEUE_PRI(_n, _p) ((_p) << (2 * _n))
+#define E1000_TQAVARBCTRL_QUEUE_PRI(_n, _p) ((_p) << (2 * (_n)))
/* QAV Tx mode control registers where _n can be 0 or 1. */
#define E1000_I210_TQAVCC(_n) (0x3004 + 0x40 * (_n))
@@ -215,7 +220,7 @@
#define E1000_PQGPTC(_n) (0x010014 + (0x100 * (_n)))
/* Queues packet buffer size masks where _n can be 0-3 and _s 0-63 [kB] */
-#define E1000_I210_TXPBS_SIZE(_n, _s) ((_s) << (6 * _n))
+#define E1000_I210_TXPBS_SIZE(_n, _s) ((_s) << (6 * (_n)))
#define E1000_MMDAC 13 /* MMD Access Control */
#define E1000_MMDAAD 14 /* MMD Access Address/Data */
@@ -552,7 +557,7 @@
#define E1000_WVBR 0x03554 /* VM Wrong Behavior - RWS */
#define E1000_RPLOLR 0x05AF0 /* Replication Offload - RW */
#define E1000_UTA 0x0A000 /* Unicast Table Array - RW */
-#define E1000_IOVTCL 0x05BBC /* IOV Control Register */
+#define E1000_IOVCTL 0x05BBC /* IOV Control Register */
#define E1000_VMRCTL 0X05D80 /* Virtual Mirror Rule Control */
#define E1000_VMRVLAN 0x05D90 /* Virtual Mirror Rule VLAN */
#define E1000_VMRVM 0x05DA0 /* Virtual Mirror Rule VM */
@@ -588,6 +593,10 @@
#define E1000_TIMADJL 0x0B60C /* Time sync time adjustment offset Low - RW */
#define E1000_TIMADJH 0x0B610 /* Time sync time adjustment offset High - RW */
#define E1000_TSAUXC 0x0B640 /* Timesync Auxiliary Control register */
+#define E1000_SYSSTMPL 0x0B648 /* HH Timesync system stamp low register */
+#define E1000_SYSSTMPH 0x0B64C /* HH Timesync system stamp hi register */
+#define E1000_PLTSTMPL 0x0B640 /* HH Timesync platform stamp low register */
+#define E1000_PLTSTMPH 0x0B644 /* HH Timesync platform stamp hi register */
#define E1000_SYSTIMR 0x0B6F8 /* System time register Residue */
#define E1000_TSICR 0x0B66C /* Interrupt Cause Register */
#define E1000_TSIM 0x0B674 /* Interrupt Mask Register */
diff --git a/usr/src/uts/common/io/e1000api/e1000_vf.c b/usr/src/uts/common/io/e1000api/e1000_vf.c
index 2cabac9fa4..4af985b87b 100644
--- a/usr/src/uts/common/io/e1000api/e1000_vf.c
+++ b/usr/src/uts/common/io/e1000api/e1000_vf.c
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2014, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/usr/src/uts/common/io/e1000api/e1000_vf.h b/usr/src/uts/common/io/e1000api/e1000_vf.h
index 2a780741c2..e6f834e78a 100644
--- a/usr/src/uts/common/io/e1000api/e1000_vf.h
+++ b/usr/src/uts/common/io/e1000api/e1000_vf.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2014, Intel Corporation
+ Copyright (c) 2001-2015, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/usr/src/uts/common/io/e1000g/e1000_osdep.h b/usr/src/uts/common/io/e1000g/e1000_osdep.h
index 303d24848b..32d1b8cfad 100644
--- a/usr/src/uts/common/io/e1000g/e1000_osdep.h
+++ b/usr/src/uts/common/io/e1000g/e1000_osdep.h
@@ -21,6 +21,8 @@
/*
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms of the CDDLv1.
+ *
+ * Copyright 2016 Joyent, Inc.
*/
#ifndef _E1000_OSDEP_H
@@ -103,8 +105,23 @@ extern "C" {
*/
#define E1000_WRITE_FLUSH(a) (void)E1000_READ_REG(a, E1000_STATUS)
+/*
+ * Note, for all of the following register defines, it's important that these be
+ * in do {} while loops that only run a single time. Previously they were formed
+ * as normal blocks. Unfortunately this would fail in the following form which
+ * is used in the common code:
+ *
+ * if (cond)
+ * E1000_WRITE_REG
+ * else
+ * ...
+ *
+ * When the E1000_WRITE_REG macros was missing the do keyword, the compiler
+ * would end up associating the outer brace of the block with the if statement
+ * and thus the else clause would get left behind.
+ */
#define E1000_WRITE_REG(hw, reg, value) \
-{\
+do { \
if ((hw)->mac.type != e1000_82542) \
ddi_put32((OS_DEP(hw))->reg_handle, \
(uint32_t *)((uintptr_t)(hw)->hw_addr + reg), \
@@ -114,7 +131,7 @@ extern "C" {
(uint32_t *)((uintptr_t)(hw)->hw_addr + \
e1000_translate_register_82542(reg)), \
value); \
-}
+} while (0)
#define E1000_READ_REG(hw, reg) (\
((hw)->mac.type != e1000_82542) ? \
@@ -125,7 +142,7 @@ extern "C" {
e1000_translate_register_82542(reg))))
#define E1000_WRITE_REG_ARRAY(hw, reg, offset, value) \
-{\
+do {\
if ((hw)->mac.type != e1000_82542) \
ddi_put32((OS_DEP(hw))->reg_handle, \
(uint32_t *)((uintptr_t)(hw)->hw_addr + \
@@ -136,7 +153,7 @@ extern "C" {
(uint32_t *)((uintptr_t)(hw)->hw_addr + \
e1000_translate_register_82542(reg) + \
((offset) << 2)), value); \
-}
+} while (0)
#define E1000_READ_REG_ARRAY(hw, reg, offset) (\
((hw)->mac.type != e1000_82542) ? \
diff --git a/usr/src/uts/common/io/e1000g/e1000g_main.c b/usr/src/uts/common/io/e1000g/e1000g_main.c
index 514b4d8e7d..f08cde4525 100644
--- a/usr/src/uts/common/io/e1000g/e1000g_main.c
+++ b/usr/src/uts/common/io/e1000g/e1000g_main.c
@@ -25,7 +25,7 @@
/*
* Copyright 2012 DEY Storage Systems, Inc. All rights reserved.
* Copyright 2013 Nexenta Systems, Inc. All rights reserved.
- * Copyright (c) 2015, Joyent, Inc.
+ * Copyright 2016 Joyent, Inc.
*/
/*
@@ -710,6 +710,17 @@ e1000g_regs_map(struct e1000g *Adapter)
goto regs_map_fail;
}
break;
+ case e1000_pch_spt:
+ /*
+ * On the SPT, the device flash is actually in BAR0, not a
+ * separate BAR. Therefore we end up setting the
+ * ich_flash_handle to be the same as the register handle.
+ * We mark the same to reduce the confusion in the other
+ * functions and macros. Though this does make the set up and
+ * tear-down path slightly more complicated.
+ */
+ osdep->ich_flash_handle = osdep->reg_handle;
+ hw->flash_address = hw->hw_addr;
default:
break;
}
@@ -769,7 +780,7 @@ e1000g_regs_map(struct e1000g *Adapter)
regs_map_fail:
if (osdep->reg_handle != NULL)
ddi_regs_map_free(&osdep->reg_handle);
- if (osdep->ich_flash_handle != NULL)
+ if (osdep->ich_flash_handle != NULL && hw->mac.type != e1000_pch_spt)
ddi_regs_map_free(&osdep->ich_flash_handle);
return (DDI_FAILURE);
}
@@ -897,6 +908,7 @@ e1000g_setup_max_mtu(struct e1000g *Adapter)
/* pch2 can do jumbo frames up to 9K */
case e1000_pch2lan:
case e1000_pch_lpt:
+ case e1000_pch_spt:
Adapter->max_mtu = MAXIMUM_MTU_9K;
break;
/* types with a special limit */
@@ -1129,7 +1141,8 @@ e1000g_unattach(dev_info_t *devinfo, struct e1000g *Adapter)
if (Adapter->attach_progress & ATTACH_PROGRESS_REGS_MAP) {
if (Adapter->osdep.reg_handle != NULL)
ddi_regs_map_free(&Adapter->osdep.reg_handle);
- if (Adapter->osdep.ich_flash_handle != NULL)
+ if (Adapter->osdep.ich_flash_handle != NULL &&
+ Adapter->shared.mac.type != e1000_pch_spt)
ddi_regs_map_free(&Adapter->osdep.ich_flash_handle);
if (Adapter->osdep.io_reg_handle != NULL)
ddi_regs_map_free(&Adapter->osdep.io_reg_handle);
@@ -1461,6 +1474,8 @@ e1000g_init(struct e1000g *Adapter)
pba = E1000_PBA_26K;
} else if (hw->mac.type == e1000_pch_lpt) {
pba = E1000_PBA_26K;
+ } else if (hw->mac.type == e1000_pch_spt) {
+ pba = E1000_PBA_26K;
} else {
/*
* Total FIFO is 40K
@@ -1686,6 +1701,12 @@ e1000g_link_up(struct e1000g *Adapter)
switch (hw->phy.media_type) {
case e1000_media_type_copper:
if (hw->mac.get_link_status) {
+ /*
+ * SPT devices need a bit of extra time before we ask
+ * them.
+ */
+ if (hw->mac.type == e1000_pch_spt)
+ msec_delay(50);
(void) e1000_check_for_link(hw);
if ((E1000_READ_REG(hw, E1000_STATUS) &
E1000_STATUS_LU)) {
@@ -1942,6 +1963,41 @@ start_fail:
return (DDI_FAILURE);
}
+/*
+ * The I219 has the curious property that if the descriptor rings are not
+ * emptied before resetting the hardware or before changing the device state
+ * based on runtime power management, it'll cause the card to hang. This can
+ * then only be fixed by a PCI reset. As such, for the I219 and it alone, we
+ * have to flush the rings if we're in this state.
+ */
+static void
+e1000g_flush_desc_rings(struct e1000g *Adapter)
+{
+ struct e1000_hw *hw = &Adapter->shared;
+ u16 hang_state;
+ u32 fext_nvm11, tdlen;
+
+ /* First, disable MULR fix in FEXTNVM11 */
+ fext_nvm11 = E1000_READ_REG(hw, E1000_FEXTNVM11);
+ fext_nvm11 |= E1000_FEXTNVM11_DISABLE_MULR_FIX;
+ E1000_WRITE_REG(hw, E1000_FEXTNVM11, fext_nvm11);
+
+ /* do nothing if we're not in faulty state, or if the queue is empty */
+ tdlen = E1000_READ_REG(hw, E1000_TDLEN(0));
+ hang_state = pci_config_get16(Adapter->osdep.cfg_handle,
+ PCICFG_DESC_RING_STATUS);
+ if (!(hang_state & FLUSH_DESC_REQUIRED) || !tdlen)
+ return;
+ e1000g_flush_tx_ring(Adapter);
+
+ /* recheck, maybe the fault is caused by the rx ring */
+ hang_state = pci_config_get16(Adapter->osdep.cfg_handle,
+ PCICFG_DESC_RING_STATUS);
+ if (hang_state & FLUSH_DESC_REQUIRED)
+ e1000g_flush_rx_ring(Adapter);
+
+}
+
static void
e1000g_m_stop(void *arg)
{
@@ -2005,6 +2061,14 @@ e1000g_stop(struct e1000g *Adapter, boolean_t global)
/* Clean the pending rx jumbo packet fragment */
e1000g_rx_clean(Adapter);
+ /*
+ * The I219, eg. the pch_spt, has bugs such that we must ensure that
+ * rings are flushed before we do anything else. This must be done
+ * before we release DMA resources.
+ */
+ if (Adapter->shared.mac.type == e1000_pch_spt)
+ e1000g_flush_desc_rings(Adapter);
+
if (global) {
e1000g_release_dma_resources(Adapter);
@@ -2453,16 +2517,17 @@ e1000g_init_unicst(struct e1000g *Adapter)
/*
* The common code does not correctly calculate the number of
- * rar's that could be reserved by firmware for the pch_lpt
- * macs. The interface has one primary rar, and 11 additional
- * ones. Those 11 additional ones are not always available.
- * According to the datasheet, we need to check a few of the
- * bits set in the FWSM register. If the value is zero,
- * everything is available. If the value is 1, none of the
+ * rar's that could be reserved by firmware for the pch_lpt and
+ * pch_spt macs. The interface has one primary rar, and 11
+ * additional ones. Those 11 additional ones are not always
+ * available. According to the datasheet, we need to check a
+ * few of the bits set in the FWSM register. If the value is
+ * zero, everything is available. If the value is 1, none of the
* additional registers are available. If the value is 2-7, only
* that number are available.
*/
- if (hw->mac.type == e1000_pch_lpt) {
+ if (hw->mac.type == e1000_pch_lpt ||
+ hw->mac.type == e1000_pch_spt) {
uint32_t locked, rar;
locked = E1000_READ_REG(hw, E1000_FWSM) &
diff --git a/usr/src/uts/common/io/e1000g/e1000g_rx.c b/usr/src/uts/common/io/e1000g/e1000g_rx.c
index 57c1d0dc94..3e12e172ed 100644
--- a/usr/src/uts/common/io/e1000g/e1000g_rx.c
+++ b/usr/src/uts/common/io/e1000g/e1000g_rx.c
@@ -24,6 +24,7 @@
/*
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2016 Joyent, Inc.
*/
/*
@@ -903,3 +904,38 @@ rx_drop:
return (ret_mp);
}
+
+/*
+ * This is part of a workaround for the I219, see e1000g_flush_desc_rings() for
+ * more information.
+ *
+ * Flush all descriptors in the rx ring and disable it.
+ */
+void
+e1000g_flush_rx_ring(struct e1000g *Adapter)
+{
+ struct e1000_hw *hw = &Adapter->shared;
+ uint32_t rctl, rxdctl;
+
+ rctl = E1000_READ_REG(hw, E1000_RCTL);
+ E1000_WRITE_REG(hw, E1000_RCTL, rctl & ~E1000_RCTL_EN);
+ E1000_WRITE_FLUSH(hw);
+ usec_delay(150);
+
+ rxdctl = E1000_READ_REG(hw, E1000_RXDCTL(0));
+ /* Zero the lower 14 bits (prefetch and host thresholds). */
+ rxdctl &= 0xffffc000;
+ /*
+ * Update thresholds: prefetch threshold to 31, host threshold to 1
+ * and make sure the granularity is "descriptors" and not "cache lines"
+ */
+ rxdctl |= (0x1F | (1 << 8) | E1000_RXDCTL_THRESH_UNIT_DESC);
+ E1000_WRITE_REG(hw, E1000_RXDCTL(0), rxdctl);
+
+ /* Momentarily enable the RX ring for the changes to take effect */
+ E1000_WRITE_REG(hw, E1000_RCTL, rctl | E1000_RCTL_EN);
+ E1000_WRITE_FLUSH(hw);
+ usec_delay(150);
+ E1000_WRITE_REG(hw, E1000_RCTL, rctl & ~E1000_RCTL_EN);
+
+}
diff --git a/usr/src/uts/common/io/e1000g/e1000g_sw.h b/usr/src/uts/common/io/e1000g/e1000g_sw.h
index 259c22b9b3..261be80b1d 100644
--- a/usr/src/uts/common/io/e1000g/e1000g_sw.h
+++ b/usr/src/uts/common/io/e1000g/e1000g_sw.h
@@ -21,6 +21,7 @@
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2012 David Höppner. All rights reserved.
+ * Copyright 2016 Joyent, Inc.
*/
#ifndef _E1000G_SW_H
@@ -1072,6 +1073,24 @@ void e1000g_set_fma_flags(int dma_flag);
int e1000g_reset_link(struct e1000g *Adapter);
/*
+ * Functions for working around various problems, these used to be from the
+ * common code.
+ */
+s32 e1000_fifo_workaround_82547(struct e1000_hw *hw, u16 length);
+void e1000_update_tx_fifo_head_82547(struct e1000_hw *hw, u32 length);
+void e1000_set_ttl_workaround_state_82541(struct e1000_hw *hw, bool state);
+bool e1000_ttl_workaround_enabled_82541(struct e1000_hw *hw);
+s32 e1000_igp_ttl_workaround_82547(struct e1000_hw *hw);
+
+/*
+ * I219 specific workarounds
+ */
+#define PCICFG_DESC_RING_STATUS 0xe4
+#define FLUSH_DESC_REQUIRED 0x100
+extern void e1000g_flush_rx_ring(struct e1000g *);
+extern void e1000g_flush_tx_ring(struct e1000g *);
+
+/*
* Global variables
*/
extern boolean_t e1000g_force_detach;
diff --git a/usr/src/uts/common/io/e1000g/e1000g_tx.c b/usr/src/uts/common/io/e1000g/e1000g_tx.c
index 1f8a51d291..80ba93aef9 100644
--- a/usr/src/uts/common/io/e1000g/e1000g_tx.c
+++ b/usr/src/uts/common/io/e1000g/e1000g_tx.c
@@ -24,7 +24,7 @@
*/
/*
- * Copyright (c) 2012, Joyent, Inc. All rights reserved.
+ * Copyright 2016 Joyent, Inc.
*/
/*
@@ -1723,3 +1723,42 @@ e1000g_82547_tx_move_tail(e1000g_tx_ring_t *tx_ring)
tx_ring->timer_enable_82547 = B_TRUE;
e1000g_82547_tx_move_tail_work(tx_ring);
}
+
+/*
+ * This is part of a workaround for the I219, see e1000g_flush_desc_rings() for
+ * more information.
+ *
+ * We need to clear any potential pending descriptors from the tx_ring. As
+ * we're about to reset the device, we don't care about the data that we give it
+ * itself.
+ */
+void
+e1000g_flush_tx_ring(struct e1000g *Adapter)
+{
+ struct e1000_hw *hw = &Adapter->shared;
+ e1000g_tx_ring_t *tx_ring = &Adapter->tx_ring[0];
+ uint32_t tctl, txd_lower = E1000_TXD_CMD_IFCS;
+ uint16_t size = 512;
+ struct e1000_tx_desc *desc;
+
+ tctl = E1000_READ_REG(hw, E1000_TCTL);
+ E1000_WRITE_REG(hw, E1000_TCTL, tctl | E1000_TCTL_EN);
+
+ desc = tx_ring->tbd_next;
+ if (tx_ring->tbd_next == tx_ring->tbd_last)
+ tx_ring->tbd_next = tx_ring->tbd_first;
+ else
+ tx_ring->tbd_next++;
+
+ /* We just need to set any valid address, so we use the ring itself */
+ desc->buffer_addr = tx_ring->tbd_dma_addr;
+ desc->lower.data = LE_32(txd_lower | size);
+ desc->upper.data = 0;
+
+ (void) ddi_dma_sync(tx_ring->tbd_dma_handle,
+ 0, 0, DDI_DMA_SYNC_FORDEV);
+ E1000_WRITE_REG(hw, E1000_TDT(0),
+ (uint32_t)(tx_ring->tbd_next - tx_ring->tbd_first));
+ (void) E1000_READ_REG(hw, E1000_STATUS);
+ usec_delay(250);
+}
diff --git a/usr/src/uts/common/io/e1000g/e1000g_workarounds.c b/usr/src/uts/common/io/e1000g/e1000g_workarounds.c
index b035cd8097..6d2751f910 100644
--- a/usr/src/uts/common/io/e1000g/e1000g_workarounds.c
+++ b/usr/src/uts/common/io/e1000g/e1000g_workarounds.c
@@ -24,6 +24,19 @@
*/
#include "e1000_api.h"
+#define E1000_FIFO_MULTIPLIER 0x80
+#define E1000_FIFO_HDR_SIZE 0x10
+#define E1000_FIFO_GRANULARITY 0x10
+#define E1000_FIFO_PAD_82547 0x3E0
+#define E1000_ERR_FIFO_WRAP 8
+
+#define DSP_RESET_ENABLE 0x0
+#define DSP_RESET_DISABLE 0x2
+#define E1000_MAX_DSP_RESETS 10
+
+#define E1000_ROUNDUP(size, unit) (((size) + (unit) - 1) & ~((unit) - 1))
+
+
/*
* e1000_ttl_workaround_enabled_82541 - Returns current TTL workaround status
* @hw: pointer to the HW structure
diff --git a/usr/src/uts/common/io/igb/igb_gld.c b/usr/src/uts/common/io/igb/igb_gld.c
index d754c79949..e9a75f5dfc 100644
--- a/usr/src/uts/common/io/igb/igb_gld.c
+++ b/usr/src/uts/common/io/igb/igb_gld.c
@@ -1375,13 +1375,15 @@ igb_set_priv_prop(igb_t *igb, const char *pr_name,
case e1000_i350:
/* Must set this prior to the set call. */
hw->dev_spec._82575.eee_disable = !result;
- if (e1000_set_eee_i350(hw) != E1000_SUCCESS)
+ if (e1000_set_eee_i350(hw, result,
+ result) != E1000_SUCCESS)
err = EIO;
break;
case e1000_i354:
/* Must set this prior to the set call. */
hw->dev_spec._82575.eee_disable = !result;
- if (e1000_set_eee_i354(hw) != E1000_SUCCESS)
+ if (e1000_set_eee_i354(hw, result,
+ result) != E1000_SUCCESS)
err = EIO;
break;
default:
diff --git a/usr/src/uts/common/io/igb/igb_main.c b/usr/src/uts/common/io/igb/igb_main.c
index 3a215116fb..23fad83ec6 100644
--- a/usr/src/uts/common/io/igb/igb_main.c
+++ b/usr/src/uts/common/io/igb/igb_main.c
@@ -26,6 +26,7 @@
/*
* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2013, Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2016 Joyent, Inc.
*/
#include "igb_sw.h"
@@ -596,9 +597,9 @@ igb_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd)
* default.
*/
if (igb->hw.mac.type == e1000_i350)
- (void) e1000_set_eee_i350(&igb->hw);
+ (void) e1000_set_eee_i350(&igb->hw, B_FALSE, B_FALSE);
else if (igb->hw.mac.type == e1000_i354)
- (void) e1000_set_eee_i354(&igb->hw);
+ (void) e1000_set_eee_i354(&igb->hw, B_FALSE, B_FALSE);
return (DDI_SUCCESS);
@@ -1864,9 +1865,9 @@ igb_start(igb_t *igb, boolean_t alloc_buffer)
goto start_failure;
if (igb->hw.mac.type == e1000_i350)
- (void) e1000_set_eee_i350(&igb->hw);
+ (void) e1000_set_eee_i350(&igb->hw, B_FALSE, B_FALSE);
else if (igb->hw.mac.type == e1000_i354)
- (void) e1000_set_eee_i354(&igb->hw);
+ (void) e1000_set_eee_i354(&igb->hw, B_FALSE, B_FALSE);
for (i = igb->num_tx_rings - 1; i >= 0; i--)
mutex_exit(&igb->tx_rings[i].tx_lock);