summaryrefslogtreecommitdiff
path: root/sys/dev/pci
diff options
context:
space:
mode:
authorMike Belopuhov <mikeb@cvs.openbsd.org>2012-08-06 21:07:53 +0000
committerMike Belopuhov <mikeb@cvs.openbsd.org>2012-08-06 21:07:53 +0000
commit244cccfed6ad64fc3b8399ca59ada5b2f19a9290 (patch)
tree4b8c542dd4b26bc637f5a84f426db1431f0d49df /sys/dev/pci
parent082fbc62061b14dfbc3fd5bb7f007bc828afc556 (diff)
Add support for 10Gb ethernet cards based on the Intel X540 chipset.
The code was obtained from FreeBSD and tested on the hardware kindly donated by Tony Sarendal <tony () polarcap ! org>. Thanks a lot! ok jsg
Diffstat (limited to 'sys/dev/pci')
-rw-r--r--sys/dev/pci/files.pci3
-rw-r--r--sys/dev/pci/if_ix.c54
-rw-r--r--sys/dev/pci/ixgbe.c61
-rw-r--r--sys/dev/pci/ixgbe.h3
-rw-r--r--sys/dev/pci/ixgbe_82599.c7
-rw-r--r--sys/dev/pci/ixgbe_phy.c26
-rw-r--r--sys/dev/pci/ixgbe_type.h63
-rw-r--r--sys/dev/pci/ixgbe_x540.c898
8 files changed, 1055 insertions, 60 deletions
diff --git a/sys/dev/pci/files.pci b/sys/dev/pci/files.pci
index 548f75b2af3..2e63091379d 100644
--- a/sys/dev/pci/files.pci
+++ b/sys/dev/pci/files.pci
@@ -1,4 +1,4 @@
-# $OpenBSD: files.pci,v 1.283 2012/08/02 17:35:52 mikeb Exp $
+# $OpenBSD: files.pci,v 1.284 2012/08/06 21:07:52 mikeb Exp $
# $NetBSD: files.pci,v 1.20 1996/09/24 17:47:15 christos Exp $
#
# Config file and device description for machine-independent PCI code.
@@ -366,6 +366,7 @@ file dev/pci/if_ix.c ix
file dev/pci/ixgbe.c ix
file dev/pci/ixgbe_82598.c ix
file dev/pci/ixgbe_82599.c ix
+file dev/pci/ixgbe_x540.c ix
file dev/pci/ixgbe_phy.c ix
# Neterion Xframe 10 Gigabit ethernet
diff --git a/sys/dev/pci/if_ix.c b/sys/dev/pci/if_ix.c
index a47bafc34cf..8875590ee4f 100644
--- a/sys/dev/pci/if_ix.c
+++ b/sys/dev/pci/if_ix.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_ix.c,v 1.66 2012/07/29 13:49:03 mikeb Exp $ */
+/* $OpenBSD: if_ix.c,v 1.67 2012/08/06 21:07:52 mikeb Exp $ */
/******************************************************************************
@@ -72,7 +72,8 @@ const struct pci_matchid ixgbe_devices[] = {
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82599_T3_LOM },
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82599_SFP },
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82599_SFP_EM },
- { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82599_SFP_FCOE }
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82599_SFP_FCOE },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_X540T },
#if 0
{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82599VF }
#endif
@@ -253,6 +254,9 @@ ixgbe_attach(struct device *parent, struct device *self, void *aux)
error = ixgbe_init_ops_vf(hw);
break;
#endif
+ case ixgbe_mac_X540:
+ error = ixgbe_init_ops_X540(hw);
+ break;
default:
error = IXGBE_ERR_DEVICE_NOT_SUPPORTED;
break;
@@ -689,7 +693,7 @@ ixgbe_init(void *arg)
gpie |= IXGBE_SDP1_GPIEN;
if (sc->hw.mac.type == ixgbe_mac_82599EB) {
- /* Add for Thermal detection */
+ /* Add for Module detection */
gpie |= IXGBE_SDP2_GPIEN;
/*
@@ -699,6 +703,17 @@ ixgbe_init(void *arg)
gpie |= 0xf << IXGBE_GPIE_LLI_DELAY_SHIFT;
}
+ if (sc->hw.mac.type == ixgbe_mac_X540) {
+ /* Thermal Failure Detection */
+ gpie |= IXGBE_SDP0_GPIEN;
+
+ /*
+ * Set LL interval to max to reduce the number of low latency
+ * interrupts hitting the card when the ring is getting full.
+ */
+ gpie |= 0xf << IXGBE_GPIE_LLI_DELAY_SHIFT;
+ }
+
if (sc->msix > 1) {
/* Enable Enhanced MSIX mode */
gpie |= IXGBE_GPIE_MSIX_MODE;
@@ -947,12 +962,20 @@ ixgbe_legacy_irq(void *arg)
/* Check for fan failure */
if ((hw->phy.media_type == ixgbe_media_type_copper) &&
(reg_eicr & IXGBE_EICR_GPI_SDP1)) {
- printf("\n%s: CRITICAL: FAN FAILURE!! "
+ printf("%s: CRITICAL: FAN FAILURE!! "
"REPLACE IMMEDIATELY!!\n", ifp->if_xname);
IXGBE_WRITE_REG(&sc->hw, IXGBE_EIMS,
IXGBE_EICR_GPI_SDP1);
}
+ /* Check for over temp condition */
+ if ((hw->mac.type == ixgbe_mac_X540) &&
+ (reg_eicr & IXGBE_EICR_GPI_SDP0)) {
+ printf("%s: CRITICAL: OVER TEMP!! "
+ "PHY IS SHUT DOWN!!\n", ifp->if_xname);
+ IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP0);
+ }
+
/* Link status change */
if (reg_eicr & IXGBE_EICR_LSC) {
timeout_del(&sc->timer);
@@ -1001,6 +1024,9 @@ ixgbe_media_status(struct ifnet * ifp, struct ifmediareq * ifmr)
ifmr->ifm_status |= IFM_ACTIVE;
switch (sc->link_speed) {
+ case IXGBE_LINK_SPEED_100_FULL:
+ ifmr->ifm_active |= IFM_100_TX | IFM_FDX;
+ break;
case IXGBE_LINK_SPEED_1GB_FULL:
ifmr->ifm_active |= IFM_1000_T | IFM_FDX;
break;
@@ -1432,6 +1458,11 @@ ixgbe_identify_hardware(struct ix_softc *sc)
sc->optics = IFM_AUTO;
sc->hw.phy.smart_speed = ixgbe_smart_speed;
break;
+ case PCI_PRODUCT_INTEL_X540T:
+ sc->hw.mac.type = ixgbe_mac_X540;
+ sc->optics = IFM_10G_T;
+ sc->hw.phy.smart_speed = ixgbe_smart_speed;
+ break;
default:
sc->optics = IFM_AUTO;
break;
@@ -1686,8 +1717,13 @@ ixgbe_config_link(struct ix_softc *sc)
if (sc->hw.mac.ops.check_link)
err = sc->hw.mac.ops.check_link(&sc->hw, &autoneg,
&sc->link_up, FALSE);
- if (err)
- return;
+ if (err)
+ return;
+ if ((!autoneg) && (sc->hw.mac.ops.get_link_capabilities))
+ err = sc->hw.mac.ops.get_link_capabilities(&sc->hw,
+ &autoneg, &negotiate);
+ if (err)
+ return;
if (sc->hw.mac.ops.setup_link)
err = sc->hw.mac.ops.setup_link(&sc->hw, autoneg,
negotiate, sc->link_up);
@@ -2047,6 +2083,7 @@ ixgbe_initialize_transmit_units(struct ix_softc *sc)
txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL(i));
break;
case ixgbe_mac_82599EB:
+ case ixgbe_mac_X540:
default:
txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(i));
break;
@@ -2057,6 +2094,7 @@ ixgbe_initialize_transmit_units(struct ix_softc *sc)
IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL(i), txctrl);
break;
case ixgbe_mac_82599EB:
+ case ixgbe_mac_X540:
default:
IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(i), txctrl);
break;
@@ -2064,7 +2102,7 @@ ixgbe_initialize_transmit_units(struct ix_softc *sc)
}
ifp->if_timer = 0;
- if (hw->mac.type == ixgbe_mac_82599EB) {
+ if (hw->mac.type != ixgbe_mac_82598EB) {
uint32_t dmatxctl, rttdcs;
dmatxctl = IXGBE_READ_REG(hw, IXGBE_DMATXCTL);
dmatxctl |= IXGBE_DMATXCTL_TE;
@@ -3230,6 +3268,7 @@ ixgbe_enable_intr(struct ix_softc *sc)
mask |= IXGBE_EIMS_GPI_SDP1;
else {
mask |= IXGBE_EIMS_ECC;
+ mask |= IXGBE_EIMS_GPI_SDP0;
mask |= IXGBE_EIMS_GPI_SDP1;
mask |= IXGBE_EIMS_GPI_SDP2;
}
@@ -3345,6 +3384,7 @@ ixgbe_set_ivar(struct ix_softc *sc, uint8_t entry, uint8_t vector, int8_t type)
break;
case ixgbe_mac_82599EB:
+ case ixgbe_mac_X540:
if (type == -1) { /* MISC IVAR */
index = (entry & 1) * 8;
ivar = IXGBE_READ_REG(hw, IXGBE_IVAR_MISC);
diff --git a/sys/dev/pci/ixgbe.c b/sys/dev/pci/ixgbe.c
index 3505cc5aa41..a35c7ca52c4 100644
--- a/sys/dev/pci/ixgbe.c
+++ b/sys/dev/pci/ixgbe.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ixgbe.c,v 1.7 2012/07/29 13:49:03 mikeb Exp $ */
+/* $OpenBSD: ixgbe.c,v 1.8 2012/08/06 21:07:52 mikeb Exp $ */
/******************************************************************************
@@ -353,6 +353,19 @@ int32_t ixgbe_clear_hw_cntrs_generic(struct ixgbe_hw *hw)
}
}
+ if (hw->mac.type == ixgbe_mac_X540) {
+ if (hw->phy.id == 0)
+ hw->phy.ops.identify(hw);
+ hw->phy.ops.read_reg(hw, IXGBE_PCRC8ECL,
+ IXGBE_MDIO_PCS_DEV_TYPE, &i);
+ hw->phy.ops.read_reg(hw, IXGBE_PCRC8ECH,
+ IXGBE_MDIO_PCS_DEV_TYPE, &i);
+ hw->phy.ops.read_reg(hw, IXGBE_LDPCECL,
+ IXGBE_MDIO_PCS_DEV_TYPE, &i);
+ hw->phy.ops.read_reg(hw, IXGBE_LDPCECH,
+ IXGBE_MDIO_PCS_DEV_TYPE, &i);
+ }
+
return IXGBE_SUCCESS;
}
@@ -1038,7 +1051,8 @@ int32_t ixgbe_acquire_eeprom(struct ixgbe_hw *hw)
uint32_t eec;
uint32_t i;
- if (ixgbe_acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) != IXGBE_SUCCESS)
+ if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM)
+ != IXGBE_SUCCESS)
status = IXGBE_ERR_SWFW_SYNC;
if (status == IXGBE_SUCCESS) {
@@ -1061,7 +1075,7 @@ int32_t ixgbe_acquire_eeprom(struct ixgbe_hw *hw)
IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
DEBUGOUT("Could not acquire EEPROM grant\n");
- ixgbe_release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
+ hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
status = IXGBE_ERR_EEPROM;
}
@@ -1368,7 +1382,7 @@ void ixgbe_release_eeprom(struct ixgbe_hw *hw)
eec &= ~IXGBE_EEC_REQ;
IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
- ixgbe_release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
+ hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
/* Delay before attempt to obtain semaphore again to allow FW access */
msec_delay(hw->eeprom.semaphore_delay);
@@ -2388,19 +2402,21 @@ int32_t ixgbe_setup_fc(struct ixgbe_hw *hw, int32_t packetbuf_num)
break;
}
- /*
- * Enable auto-negotiation between the MAC & PHY;
- * the MAC will advertise clause 37 flow control.
- */
- IXGBE_WRITE_REG(hw, IXGBE_PCS1GANA, reg);
- reg = IXGBE_READ_REG(hw, IXGBE_PCS1GLCTL);
+ if (hw->mac.type != ixgbe_mac_X540) {
+ /*
+ * Enable auto-negotiation between the MAC & PHY;
+ * the MAC will advertise clause 37 flow control.
+ */
+ IXGBE_WRITE_REG(hw, IXGBE_PCS1GANA, reg);
+ reg = IXGBE_READ_REG(hw, IXGBE_PCS1GLCTL);
- /* Disable AN timeout */
- if (hw->fc.strict_ieee)
- reg &= ~IXGBE_PCS1GLCTL_AN_1G_TIMEOUT_EN;
+ /* Disable AN timeout */
+ if (hw->fc.strict_ieee)
+ reg &= ~IXGBE_PCS1GLCTL_AN_1G_TIMEOUT_EN;
- IXGBE_WRITE_REG(hw, IXGBE_PCS1GLCTL, reg);
- DEBUGOUT1("Set up FC; PCS1GLCTL = 0x%08X\n", reg);
+ IXGBE_WRITE_REG(hw, IXGBE_PCS1GLCTL, reg);
+ DEBUGOUT1("Set up FC; PCS1GLCTL = 0x%08X\n", reg);
+ }
/*
* AUTOC restart handles negotiation of 1G and 10G on backplane
@@ -2495,13 +2511,12 @@ out:
return status;
}
-
/**
* ixgbe_acquire_swfw_sync - Acquire SWFW semaphore
* @hw: pointer to hardware structure
* @mask: Mask to specify which semaphore to acquire
*
- * Acquires the SWFW semaphore thought the GSSR register for the specified
+ * Acquires the SWFW semaphore through the GSSR register for the specified
* function (CSR, PHY0, PHY1, EEPROM, Flash)
**/
int32_t ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, uint16_t mask)
@@ -2549,7 +2564,7 @@ int32_t ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, uint16_t mask)
* @hw: pointer to hardware structure
* @mask: Mask to specify which semaphore to release
*
- * Releases the SWFW semaphore thought the GSSR register for the specified
+ * Releases the SWFW semaphore through the GSSR register for the specified
* function (CSR, PHY0, PHY1, EEPROM, Flash)
**/
void ixgbe_release_swfw_sync(struct ixgbe_hw *hw, uint16_t mask)
@@ -3107,6 +3122,8 @@ int32_t ixgbe_check_mac_link_generic(struct ixgbe_hw *hw, ixgbe_link_speed *spee
int32_t ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw)
{
switch (hw->device_id) {
+ case IXGBE_DEV_ID_X540T:
+ return IXGBE_SUCCESS;
case IXGBE_DEV_ID_82599_T3_LOM:
return IXGBE_SUCCESS;
default:
@@ -3722,8 +3739,10 @@ int32_t ixgbe_check_for_rst_pf(struct ixgbe_hw *hw, uint16_t vf_number)
case ixgbe_mac_82599EB:
vflre = IXGBE_READ_REG(hw, IXGBE_VFLRE(reg_offset));
break;
+ case ixgbe_mac_X540:
+ vflre = IXGBE_READ_REG(hw, IXGBE_VFLREC(reg_offset));
+ break;
default:
- goto out;
break;
}
@@ -3733,7 +3752,6 @@ int32_t ixgbe_check_for_rst_pf(struct ixgbe_hw *hw, uint16_t vf_number)
hw->mbx.stats.rsts++;
}
-out:
return ret_val;
}
@@ -3851,7 +3869,8 @@ void ixgbe_init_mbx_params_pf(struct ixgbe_hw *hw)
{
struct ixgbe_mbx_info *mbx = &hw->mbx;
- if (hw->mac.type != ixgbe_mac_82599EB)
+ if (hw->mac.type != ixgbe_mac_82599EB &&
+ hw->mac.type != ixgbe_mac_X540)
return;
mbx->timeout = 0;
diff --git a/sys/dev/pci/ixgbe.h b/sys/dev/pci/ixgbe.h
index bd0318c8b61..dae9210f9d2 100644
--- a/sys/dev/pci/ixgbe.h
+++ b/sys/dev/pci/ixgbe.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ixgbe.h,v 1.9 2012/07/29 13:49:03 mikeb Exp $ */
+/* $OpenBSD: ixgbe.h,v 1.10 2012/08/06 21:07:52 mikeb Exp $ */
/******************************************************************************
@@ -253,6 +253,7 @@ uint32_t ixgbe_atr_compute_hash_82599(union ixgbe_atr_input *input, uint32_t key
int32_t ixgbe_init_ops_82598(struct ixgbe_hw *hw);
int32_t ixgbe_init_ops_82599(struct ixgbe_hw *hw);
+int32_t ixgbe_init_ops_X540(struct ixgbe_hw *hw);
/* PHY */
int32_t ixgbe_init_phy_ops_generic(struct ixgbe_hw *hw);
diff --git a/sys/dev/pci/ixgbe_82599.c b/sys/dev/pci/ixgbe_82599.c
index ee12b1f856f..dd40b1e2250 100644
--- a/sys/dev/pci/ixgbe_82599.c
+++ b/sys/dev/pci/ixgbe_82599.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ixgbe_82599.c,v 1.4 2012/07/29 13:49:03 mikeb Exp $ */
+/* $OpenBSD: ixgbe_82599.c,v 1.5 2012/08/06 21:07:52 mikeb Exp $ */
/******************************************************************************
@@ -190,7 +190,8 @@ int32_t ixgbe_setup_sfp_modules_82599(struct ixgbe_hw *hw)
goto setup_sfp_out;
/* PHY config will finish before releasing the semaphore */
- ret_val = ixgbe_acquire_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM);
+ ret_val = hw->mac.ops.acquire_swfw_sync(hw,
+ IXGBE_GSSR_MAC_CSR_SM);
if (ret_val != IXGBE_SUCCESS) {
ret_val = IXGBE_ERR_SWFW_SYNC;
goto setup_sfp_out;
@@ -204,7 +205,7 @@ int32_t ixgbe_setup_sfp_modules_82599(struct ixgbe_hw *hw)
}
/* Release the semaphore */
- ixgbe_release_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM);
+ hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM);
/* Delay obtaining semaphore again to allow FW access */
msec_delay(hw->eeprom.semaphore_delay);
diff --git a/sys/dev/pci/ixgbe_phy.c b/sys/dev/pci/ixgbe_phy.c
index c52a7a4a4e6..2abe3fce4a1 100644
--- a/sys/dev/pci/ixgbe_phy.c
+++ b/sys/dev/pci/ixgbe_phy.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ixgbe_phy.c,v 1.7 2012/07/29 13:49:03 mikeb Exp $ */
+/* $OpenBSD: ixgbe_phy.c,v 1.8 2012/08/06 21:07:52 mikeb Exp $ */
/******************************************************************************
@@ -187,7 +187,7 @@ enum ixgbe_phy_type ixgbe_get_phy_type_from_id(uint32_t phy_id)
case TN1010_PHY_ID:
phy_type = ixgbe_phy_tn;
break;
- case AQ1002_PHY_ID:
+ case X540_PHY_ID:
phy_type = ixgbe_phy_aq;
break;
case QT2022_PHY_ID:
@@ -278,7 +278,7 @@ int32_t ixgbe_read_phy_reg_generic(struct ixgbe_hw *hw, uint32_t reg_addr,
else
gssr = IXGBE_GSSR_PHY0_SM;
- if (ixgbe_acquire_swfw_sync(hw, gssr) != IXGBE_SUCCESS)
+ if (hw->mac.ops.acquire_swfw_sync(hw, gssr) != IXGBE_SUCCESS)
status = IXGBE_ERR_SWFW_SYNC;
if (status == IXGBE_SUCCESS) {
@@ -349,7 +349,7 @@ int32_t ixgbe_read_phy_reg_generic(struct ixgbe_hw *hw, uint32_t reg_addr,
}
}
- ixgbe_release_swfw_sync(hw, gssr);
+ hw->mac.ops.release_swfw_sync(hw, gssr);
}
return status;
@@ -375,7 +375,7 @@ int32_t ixgbe_write_phy_reg_generic(struct ixgbe_hw *hw, uint32_t reg_addr,
else
gssr = IXGBE_GSSR_PHY0_SM;
- if (ixgbe_acquire_swfw_sync(hw, gssr) != IXGBE_SUCCESS)
+ if (hw->mac.ops.acquire_swfw_sync(hw, gssr) != IXGBE_SUCCESS)
status = IXGBE_ERR_SWFW_SYNC;
if (status == IXGBE_SUCCESS) {
@@ -441,7 +441,7 @@ int32_t ixgbe_write_phy_reg_generic(struct ixgbe_hw *hw, uint32_t reg_addr,
}
}
- ixgbe_release_swfw_sync(hw, gssr);
+ hw->mac.ops.release_swfw_sync(hw, gssr);
}
return status;
@@ -503,7 +503,8 @@ int32_t ixgbe_setup_phy_link_generic(struct ixgbe_hw *hw)
IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
&autoneg_reg);
- autoneg_reg &= ~IXGBE_MII_100BASE_T_ADVERTISE;
+ autoneg_reg &= ~(IXGBE_MII_100BASE_T_ADVERTISE |
+ IXGBE_MII_100BASE_T_ADVERTISE_HALF);
if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_100_FULL)
autoneg_reg |= IXGBE_MII_100BASE_T_ADVERTISE;
@@ -1295,7 +1296,8 @@ int32_t ixgbe_read_i2c_byte_generic(struct ixgbe_hw *hw, uint8_t byte_offset,
swfw_mask = IXGBE_GSSR_PHY0_SM;
do {
- if (ixgbe_acquire_swfw_sync(hw, swfw_mask) != IXGBE_SUCCESS) {
+ if (hw->mac.ops.acquire_swfw_sync(hw, swfw_mask)
+ != IXGBE_SUCCESS) {
status = IXGBE_ERR_SWFW_SYNC;
goto read_byte_out;
}
@@ -1342,7 +1344,7 @@ int32_t ixgbe_read_i2c_byte_generic(struct ixgbe_hw *hw, uint8_t byte_offset,
break;
fail:
- ixgbe_release_swfw_sync(hw, swfw_mask);
+ hw->mac.ops.release_swfw_sync(hw, swfw_mask);
msec_delay(100);
ixgbe_i2c_bus_clear(hw);
retry++;
@@ -1353,7 +1355,7 @@ fail:
} while (retry < max_retry);
- ixgbe_release_swfw_sync(hw, swfw_mask);
+ hw->mac.ops.release_swfw_sync(hw, swfw_mask);
read_byte_out:
return status;
@@ -1381,7 +1383,7 @@ int32_t ixgbe_write_i2c_byte_generic(struct ixgbe_hw *hw, uint8_t byte_offset,
else
swfw_mask = IXGBE_GSSR_PHY0_SM;
- if (ixgbe_acquire_swfw_sync(hw, swfw_mask) != IXGBE_SUCCESS) {
+ if (hw->mac.ops.acquire_swfw_sync(hw, swfw_mask) != IXGBE_SUCCESS) {
status = IXGBE_ERR_SWFW_SYNC;
goto write_byte_out;
}
@@ -1425,7 +1427,7 @@ fail:
DEBUGOUT("I2C byte write error.\n");
} while (retry < max_retry);
- ixgbe_release_swfw_sync(hw, swfw_mask);
+ hw->mac.ops.release_swfw_sync(hw, swfw_mask);
write_byte_out:
return status;
diff --git a/sys/dev/pci/ixgbe_type.h b/sys/dev/pci/ixgbe_type.h
index ed810845e18..14424a42ba8 100644
--- a/sys/dev/pci/ixgbe_type.h
+++ b/sys/dev/pci/ixgbe_type.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ixgbe_type.h,v 1.11 2012/07/29 13:49:03 mikeb Exp $ */
+/* $OpenBSD: ixgbe_type.h,v 1.12 2012/08/06 21:07:52 mikeb Exp $ */
/******************************************************************************
@@ -56,17 +56,21 @@
#define IXGBE_DEV_ID_82598EB_XF_LR 0x10F4
#define IXGBE_DEV_ID_82599_KX4 0x10F7
#define IXGBE_DEV_ID_82599_KX4_MEZZ 0x1514
+#define IXGBE_DEV_ID_82599_KR 0x1517
#define IXGBE_DEV_ID_82599_COMBO_BACKPLANE 0x10F8
#define IXGBE_SUBDEV_ID_82599_KX4_KR_MEZZ 0x000C
#define IXGBE_DEV_ID_82599_CX4 0x10F9
#define IXGBE_DEV_ID_82599_SFP 0x10FB
#define IXGBE_DEV_ID_82599_SFP_EM 0x1507
#define IXGBE_SUBDEV_ID_82599_SFP 0x11A9
+#define IXGBE_SUBDEV_ID_82599_560FLR 0x17D0
#define IXGBE_DEV_ID_82599_BACKPLANE_FCOE 0x152A
#define IXGBE_DEV_ID_82599_SFP_FCOE 0x1529
#define IXGBE_DEV_ID_82599_XAUI_LOM 0x10FC
#define IXGBE_DEV_ID_82599_T3_LOM 0x151C
#define IXGBE_DEV_ID_82599_VF 0x10ED
+#define IXGBE_DEV_ID_X540_VF 0x1515
+#define IXGBE_DEV_ID_X540T 0x1528
/* General Registers */
#define IXGBE_CTRL 0x00000
@@ -157,19 +161,19 @@
/* Receive DMA Registers */
#define IXGBE_RDBAL(_i) (((_i) < 64) ? (0x01000 + ((_i) * 0x40)) : \
- (0x0D000 + ((_i - 64) * 0x40)))
+ (0x0D000 + (((_i) - 64) * 0x40)))
#define IXGBE_RDBAH(_i) (((_i) < 64) ? (0x01004 + ((_i) * 0x40)) : \
- (0x0D004 + ((_i - 64) * 0x40)))
+ (0x0D004 + (((_i) - 64) * 0x40)))
#define IXGBE_RDLEN(_i) (((_i) < 64) ? (0x01008 + ((_i) * 0x40)) : \
- (0x0D008 + ((_i - 64) * 0x40)))
+ (0x0D008 + (((_i) - 64) * 0x40)))
#define IXGBE_RDH(_i) (((_i) < 64) ? (0x01010 + ((_i) * 0x40)) : \
- (0x0D010 + ((_i - 64) * 0x40)))
+ (0x0D010 + (((_i) - 64) * 0x40)))
#define IXGBE_RDT(_i) (((_i) < 64) ? (0x01018 + ((_i) * 0x40)) : \
- (0x0D018 + ((_i - 64) * 0x40)))
+ (0x0D018 + (((_i) - 64) * 0x40)))
#define IXGBE_RXDCTL(_i) (((_i) < 64) ? (0x01028 + ((_i) * 0x40)) : \
- (0x0D028 + ((_i - 64) * 0x40)))
+ (0x0D028 + (((_i) - 64) * 0x40)))
#define IXGBE_RSCCTL(_i) (((_i) < 64) ? (0x0102C + ((_i) * 0x40)) : \
- (0x0D02C + ((_i - 64) * 0x40)))
+ (0x0D02C + (((_i) - 64) * 0x40)))
#define IXGBE_RSCDBU 0x03028
#define IXGBE_RDDCC 0x02F20
#define IXGBE_RXMEMWRAP 0x03190
@@ -181,8 +185,8 @@
* 64-127: 0x0D014 + (n-64)*0x40
*/
#define IXGBE_SRRCTL(_i) (((_i) <= 15) ? (0x02100 + ((_i) * 4)) : \
- (((_i) < 64) ? (0x01014 + ((_i) * 0x40)) : \
- (0x0D014 + ((_i - 64) * 0x40))))
+ (((_i) < 64) ? (0x01014 + ((_i) * 0x40)) : \
+ (0x0D014 + (((_i) - 64) * 0x40))))
/*
* Rx DCA Control Register:
* 00-15 : 0x02200 + n*4
@@ -190,16 +194,15 @@
* 64-127: 0x0D00C + (n-64)*0x40
*/
#define IXGBE_DCA_RXCTRL(_i) (((_i) <= 15) ? (0x02200 + ((_i) * 4)) : \
- (((_i) < 64) ? (0x0100C + ((_i) * 0x40)) : \
- (0x0D00C + ((_i - 64) * 0x40))))
+ (((_i) < 64) ? (0x0100C + ((_i) * 0x40)) : \
+ (0x0D00C + (((_i) - 64) * 0x40))))
#define IXGBE_RDRXCTL 0x02F00
#define IXGBE_RDRXCTL_RSC_PUSH 0x80
+/* 8 of these 0x03C00 - 0x03C1C */
#define IXGBE_RXPBSIZE(_i) (0x03C00 + ((_i) * 4))
- /* 8 of these 0x03C00 - 0x03C1C */
#define IXGBE_RXCTRL 0x03000
#define IXGBE_DROPEN 0x03D04
#define IXGBE_RXPBSIZE_SHIFT 10
-
/* Receive Registers */
#define IXGBE_RXCSUM 0x05000
#define IXGBE_RFCTL 0x05008
@@ -685,6 +688,26 @@
#define IXGBE_FCOEDWTC 0x08788 /* Number of FCoE DWords Transmitted */
#define IXGBE_FCCRC_CNT_MASK 0x0000FFFF /* CRC_CNT: bit 0 - 15 */
#define IXGBE_FCLAST_CNT_MASK 0x0000FFFF /* Last_CNT: bit 0 - 15 */
+#define IXGBE_O2BGPTC 0x041C4
+#define IXGBE_O2BSPC 0x087B0
+#define IXGBE_B2OSPC 0x041C0
+#define IXGBE_B2OGPRC 0x02F90
+#define IXGBE_BUPRC 0x04180
+#define IXGBE_BMPRC 0x04184
+#define IXGBE_BBPRC 0x04188
+#define IXGBE_BUPTC 0x0418C
+#define IXGBE_BMPTC 0x04190
+#define IXGBE_BBPTC 0x04194
+#define IXGBE_BCRCERRS 0x04198
+#define IXGBE_BXONRXC 0x0419C
+#define IXGBE_BXOFFRXC 0x041E0
+#define IXGBE_BXONTXC 0x041E4
+#define IXGBE_BXOFFTXC 0x041E8
+#define IXGBE_PCRC8ECL 0x0E810
+#define IXGBE_PCRC8ECH 0x0E811
+#define IXGBE_PCRC8ECH_MASK 0x1F
+#define IXGBE_LDPCECL 0x0E820
+#define IXGBE_LDPCECH 0x0E821
/* Management */
#define IXGBE_MAVTV(_i) (0x05010 + ((_i) * 4)) /* 8 of these (0-7) */
@@ -877,6 +900,7 @@
#define IXGBE_AUTOC3 0x042AC
#define IXGBE_ANLP1 0x042B0
#define IXGBE_ANLP2 0x042B4
+#define IXGBE_MACC 0x04330
#define IXGBE_ATLASCTL 0x04800
#define IXGBE_MMNGC 0x042D0
#define IXGBE_ANLPNP1 0x042D4
@@ -941,6 +965,7 @@
#define IXGBE_CTRL_GIO_DIS 0x00000004 /* Global IO Master Disable bit */
#define IXGBE_CTRL_LNK_RST 0x00000008 /* Link Reset. Resets everything. */
#define IXGBE_CTRL_RST 0x04000000 /* Reset (SW) */
+#define IXGBE_CTRL_RST_MASK (IXGBE_CTRL_LNK_RST | IXGBE_CTRL_RST)
/* FACTPS */
#define IXGBE_FACTPS_LFS 0x40000000 /* LAN Function Select */
@@ -1072,6 +1097,7 @@
#define IXGBE_MII_1GBASE_T_ADVERTISE_XNP_TX 0x4000 /* full duplex, bit:14*/
#define IXGBE_MII_1GBASE_T_ADVERTISE 0x8000 /* full duplex, bit:15*/
#define IXGBE_MII_100BASE_T_ADVERTISE 0x0100 /* full duplex, bit:8 */
+#define IXGBE_MII_100BASE_T_ADVERTISE_HALF 0x0080 /* half duplex, bit:7 */
#define IXGBE_MII_RESTART 0x200
#define IXGBE_MII_AUTONEG_COMPLETE 0x20
#define IXGBE_MII_AUTONEG_LINK_UP 0x04
@@ -1083,7 +1109,7 @@
/* PHY IDs*/
#define TN1010_PHY_ID 0x00A19410
#define TNX_FW_REV 0xB
-#define AQ1002_PHY_ID 0x03A1B420
+#define X540_PHY_ID 0x01540200
#define AQ_FW_REV 0x20
#define QT2022_PHY_ID 0x0043A400
#define ATH_PHY_ID 0x03429050
@@ -1517,6 +1543,10 @@
#define IXGBE_AUTOC2_10G_XFI (0x1 << IXGBE_AUTOC2_10G_SERIAL_PMA_PMD_SHIFT)
#define IXGBE_AUTOC2_10G_SFI (0x2 << IXGBE_AUTOC2_10G_SERIAL_PMA_PMD_SHIFT)
+#define IXGBE_MACC_FLU 0x00000001
+#define IXGBE_MACC_FSV_10G 0x00030000
+#define IXGBE_MACC_FS 0x00040000
+#define IXGBE_MAC_RX2TX_LPBK 0x00000002
/* LINKS Bit Masks */
#define IXGBE_LINKS_KX_AN_COMP 0x80000000
@@ -1583,6 +1613,7 @@
#define IXGBE_GSSR_PHY1_SM 0x0004
#define IXGBE_GSSR_MAC_CSR_SM 0x0008
#define IXGBE_GSSR_FLASH_SM 0x0010
+#define IXGBE_GSSR_SW_MNG_SM 0x0400
/* EEC Register */
#define IXGBE_EEC_SK 0x00000001 /* EEPROM Clock */
@@ -2388,6 +2419,8 @@ enum ixgbe_mac_type {
ixgbe_mac_82598EB,
ixgbe_mac_82599EB,
ixgbe_mac_82599_vf,
+ ixgbe_mac_X540,
+ ixgbe_mac_X540_vf,
ixgbe_num_macs
};
diff --git a/sys/dev/pci/ixgbe_x540.c b/sys/dev/pci/ixgbe_x540.c
new file mode 100644
index 00000000000..218056aa827
--- /dev/null
+++ b/sys/dev/pci/ixgbe_x540.c
@@ -0,0 +1,898 @@
+/* $OpenBSD: ixgbe_x540.c,v 1.1 2012/08/06 21:07:52 mikeb Exp $ */
+
+/******************************************************************************
+
+ Copyright (c) 2001-2012, Intel Corporation
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of the Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+/*$FreeBSD: src/sys/dev/ixgbe/ixgbe_x540.c,v 1.2 2012/07/05 20:51:44 jfv Exp $*/
+
+#include <dev/pci/ixgbe.h>
+#include <dev/pci/ixgbe_type.h>
+
+int32_t ixgbe_update_flash_X540(struct ixgbe_hw *hw);
+int32_t ixgbe_poll_flash_update_done_X540(struct ixgbe_hw *hw);
+int32_t ixgbe_get_swfw_sync_semaphore(struct ixgbe_hw *hw);
+void ixgbe_release_swfw_sync_semaphore(struct ixgbe_hw *hw);
+
+enum ixgbe_media_type ixgbe_get_media_type_X540(struct ixgbe_hw *hw);
+int32_t ixgbe_setup_mac_link_X540(struct ixgbe_hw *hw, ixgbe_link_speed speed,
+ int autoneg, int link_up_wait_to_complete);
+int32_t ixgbe_reset_hw_X540(struct ixgbe_hw *hw);
+int32_t ixgbe_start_hw_X540(struct ixgbe_hw *hw);
+uint32_t ixgbe_get_supported_physical_layer_X540(struct ixgbe_hw *hw);
+
+int32_t ixgbe_init_eeprom_params_X540(struct ixgbe_hw *hw);
+int32_t ixgbe_read_eerd_X540(struct ixgbe_hw *hw, uint16_t offset, uint16_t *data);
+int32_t ixgbe_write_eewr_X540(struct ixgbe_hw *hw, uint16_t offset, uint16_t data);
+int32_t ixgbe_update_eeprom_checksum_X540(struct ixgbe_hw *hw);
+int32_t ixgbe_validate_eeprom_checksum_X540(struct ixgbe_hw *hw, uint16_t *checksum_val);
+uint16_t ixgbe_calc_eeprom_checksum_X540(struct ixgbe_hw *hw);
+
+int32_t ixgbe_acquire_swfw_sync_X540(struct ixgbe_hw *hw, uint16_t mask);
+void ixgbe_release_swfw_sync_X540(struct ixgbe_hw *hw, uint16_t mask);
+
+int32_t ixgbe_blink_led_start_X540(struct ixgbe_hw *hw, uint32_t index);
+int32_t ixgbe_blink_led_stop_X540(struct ixgbe_hw *hw, uint32_t index);
+
+/**
+ * ixgbe_init_ops_X540 - Inits func ptrs and MAC type
+ * @hw: pointer to hardware structure
+ *
+ * Initialize the function pointers and assign the MAC type for X540.
+ * Does not touch the hardware.
+ **/
+int32_t ixgbe_init_ops_X540(struct ixgbe_hw *hw)
+{
+ struct ixgbe_mac_info *mac = &hw->mac;
+ struct ixgbe_phy_info *phy = &hw->phy;
+ struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
+ int32_t ret_val;
+
+ DEBUGFUNC("ixgbe_init_ops_X540");
+
+ ret_val = ixgbe_init_phy_ops_generic(hw);
+ ret_val = ixgbe_init_ops_generic(hw);
+
+ /* EEPROM */
+ eeprom->ops.init_params = &ixgbe_init_eeprom_params_X540;
+ eeprom->ops.read = &ixgbe_read_eerd_X540;
+ eeprom->ops.write = &ixgbe_write_eewr_X540;
+ eeprom->ops.update_checksum = &ixgbe_update_eeprom_checksum_X540;
+ eeprom->ops.validate_checksum = &ixgbe_validate_eeprom_checksum_X540;
+ eeprom->ops.calc_checksum = &ixgbe_calc_eeprom_checksum_X540;
+
+ /* PHY */
+ phy->ops.init = &ixgbe_init_phy_ops_generic;
+ phy->ops.reset = NULL;
+
+ /* MAC */
+ mac->ops.reset_hw = &ixgbe_reset_hw_X540;
+ mac->ops.enable_relaxed_ordering = &ixgbe_enable_relaxed_ordering_gen2;
+ mac->ops.get_media_type = &ixgbe_get_media_type_X540;
+ mac->ops.get_supported_physical_layer =
+ &ixgbe_get_supported_physical_layer_X540;
+ mac->ops.read_analog_reg8 = NULL;
+ mac->ops.write_analog_reg8 = NULL;
+ mac->ops.start_hw = &ixgbe_start_hw_X540;
+ mac->ops.get_device_caps = &ixgbe_get_device_caps_generic;
+ mac->ops.acquire_swfw_sync = &ixgbe_acquire_swfw_sync_X540;
+ mac->ops.release_swfw_sync = &ixgbe_release_swfw_sync_X540;
+
+ /* RAR, Multicast, VLAN */
+ mac->ops.set_vmdq = &ixgbe_set_vmdq_generic;
+ mac->ops.clear_vmdq = &ixgbe_clear_vmdq_generic;
+ mac->ops.insert_mac_addr = &ixgbe_insert_mac_addr_generic;
+ mac->ops.insert_mac_addr = &ixgbe_insert_mac_addr_generic;
+ mac->rar_highwater = 1;
+ mac->ops.set_vfta = &ixgbe_set_vfta_generic;
+ mac->ops.clear_vfta = &ixgbe_clear_vfta_generic;
+
+ /* Link */
+ mac->ops.get_link_capabilities =
+ &ixgbe_get_copper_link_capabilities_generic;
+ mac->ops.setup_link = &ixgbe_setup_mac_link_X540;
+ mac->ops.check_link = &ixgbe_check_mac_link_generic;
+
+ mac->mcft_size = 128;
+ mac->vft_size = 128;
+ mac->num_rar_entries = 128;
+ mac->rx_pb_size = 384;
+ mac->max_tx_queues = 128;
+ mac->max_rx_queues = 128;
+ mac->max_msix_vectors = ixgbe_get_pcie_msix_count_generic(hw);
+
+ hw->mbx.ops.init_params = ixgbe_init_mbx_params_pf;
+
+ /* LEDs */
+ mac->ops.blink_led_start = ixgbe_blink_led_start_X540;
+ mac->ops.blink_led_stop = ixgbe_blink_led_stop_X540;
+
+ return ret_val;
+}
+
+/**
+ * ixgbe_get_media_type_X540 - Get media type
+ * @hw: pointer to hardware structure
+ *
+ * Returns the media type (fiber, copper, backplane)
+ **/
+enum ixgbe_media_type ixgbe_get_media_type_X540(struct ixgbe_hw *hw)
+{
+ UNREFERENCED_PARAMETER(hw);
+ return ixgbe_media_type_copper;
+}
+
+/**
+ * ixgbe_setup_mac_link_X540 - Sets the auto advertised capabilities
+ * @hw: pointer to hardware structure
+ * @speed: new link speed
+ * @autoneg: TRUE if autonegotiation enabled
+ * @autoneg_wait_to_complete: TRUE when waiting for completion is needed
+ **/
+int32_t ixgbe_setup_mac_link_X540(struct ixgbe_hw *hw,
+ ixgbe_link_speed speed, int autoneg,
+ int autoneg_wait_to_complete)
+{
+ DEBUGFUNC("ixgbe_setup_mac_link_X540");
+ return hw->phy.ops.setup_link_speed(hw, speed, autoneg,
+ autoneg_wait_to_complete);
+}
+
+/**
+ * ixgbe_reset_hw_X540 - Perform hardware reset
+ * @hw: pointer to hardware structure
+ *
+ * Resets the hardware by resetting the transmit and receive units, masks
+ * and clears all interrupts, and perform a reset.
+ **/
+int32_t ixgbe_reset_hw_X540(struct ixgbe_hw *hw)
+{
+ int32_t status;
+ uint32_t ctrl, i;
+
+ DEBUGFUNC("ixgbe_reset_hw_X540");
+
+ /* Call adapter stop to disable tx/rx and clear interrupts */
+ status = hw->mac.ops.stop_adapter(hw);
+ if (status != IXGBE_SUCCESS)
+ goto reset_hw_out;
+
+mac_reset_top:
+ ctrl = IXGBE_CTRL_RST;
+ ctrl |= IXGBE_READ_REG(hw, IXGBE_CTRL);
+ IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl);
+ IXGBE_WRITE_FLUSH(hw);
+
+ /* Poll for reset bit to self-clear indicating reset is complete */
+ for (i = 0; i < 10; i++) {
+ usec_delay(1);
+ ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL);
+ if (!(ctrl & IXGBE_CTRL_RST_MASK))
+ break;
+ }
+
+ if (ctrl & IXGBE_CTRL_RST_MASK) {
+ status = IXGBE_ERR_RESET_FAILED;
+ DEBUGOUT("Reset polling failed to complete.\n");
+ }
+ msec_delay(100);
+
+ /*
+ * Double resets are required for recovery from certain error
+ * conditions. Between resets, it is necessary to stall to allow time
+ * for any pending HW events to complete.
+ */
+ if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) {
+ hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED;
+ goto mac_reset_top;
+ }
+
+ /* Set the Rx packet buffer size. */
+ IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(0), 384 << IXGBE_RXPBSIZE_SHIFT);
+
+ /* Store the permanent mac address */
+ hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr);
+
+ /*
+ * Store MAC address from RAR0, clear receive address registers, and
+ * clear the multicast table. Also reset num_rar_entries to 128,
+ * since we modify this value when programming the SAN MAC address.
+ */
+ hw->mac.num_rar_entries = 128;
+ hw->mac.ops.init_rx_addrs(hw);
+
+#if 0
+ /* Store the permanent SAN mac address */
+ hw->mac.ops.get_san_mac_addr(hw, hw->mac.san_addr);
+
+ /* Add the SAN MAC address to the RAR only if it's a valid address */
+ if (ixgbe_validate_mac_addr(hw->mac.san_addr) == 0) {
+ hw->mac.ops.set_rar(hw, hw->mac.num_rar_entries - 1,
+ hw->mac.san_addr, 0, IXGBE_RAH_AV);
+
+ /* Save the SAN MAC RAR index */
+ hw->mac.san_mac_rar_index = hw->mac.num_rar_entries - 1;
+
+ /* Reserve the last RAR for the SAN MAC address */
+ hw->mac.num_rar_entries--;
+ }
+
+ /* Store the alternative WWNN/WWPN prefix */
+ hw->mac.ops.get_wwn_prefix(hw, &hw->mac.wwnn_prefix,
+ &hw->mac.wwpn_prefix);
+#endif
+
+reset_hw_out:
+ return status;
+}
+
+/**
+ * ixgbe_start_hw_X540 - Prepare hardware for Tx/Rx
+ * @hw: pointer to hardware structure
+ *
+ * Starts the hardware using the generic start_hw function
+ * and the generation start_hw function.
+ * Then performs revision-specific operations, if any.
+ **/
+int32_t ixgbe_start_hw_X540(struct ixgbe_hw *hw)
+{
+ int32_t ret_val = IXGBE_SUCCESS;
+
+ DEBUGFUNC("ixgbe_start_hw_X540");
+
+ ret_val = ixgbe_start_hw_generic(hw);
+ if (ret_val != IXGBE_SUCCESS)
+ goto out;
+
+ ret_val = ixgbe_start_hw_gen2(hw);
+
+out:
+ return ret_val;
+}
+
+/**
+ * ixgbe_get_supported_physical_layer_X540 - Returns physical layer type
+ * @hw: pointer to hardware structure
+ *
+ * Determines physical layer capabilities of the current configuration.
+ **/
+uint32_t ixgbe_get_supported_physical_layer_X540(struct ixgbe_hw *hw)
+{
+ uint32_t physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
+ uint16_t ext_ability = 0;
+
+ DEBUGFUNC("ixgbe_get_supported_physical_layer_X540");
+
+ hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_EXT_ABILITY,
+ IXGBE_MDIO_PMA_PMD_DEV_TYPE, &ext_ability);
+ if (ext_ability & IXGBE_MDIO_PHY_10GBASET_ABILITY)
+ physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_T;
+ if (ext_ability & IXGBE_MDIO_PHY_1000BASET_ABILITY)
+ physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_T;
+ if (ext_ability & IXGBE_MDIO_PHY_100BASETX_ABILITY)
+ physical_layer |= IXGBE_PHYSICAL_LAYER_100BASE_TX;
+
+ return physical_layer;
+}
+
+/**
+ * ixgbe_init_eeprom_params_X540 - Initialize EEPROM params
+ * @hw: pointer to hardware structure
+ *
+ * Initializes the EEPROM parameters ixgbe_eeprom_info within the
+ * ixgbe_hw struct in order to set up EEPROM access.
+ **/
+int32_t ixgbe_init_eeprom_params_X540(struct ixgbe_hw *hw)
+{
+ struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
+ uint32_t eec;
+ uint16_t eeprom_size;
+
+ DEBUGFUNC("ixgbe_init_eeprom_params_X540");
+
+ if (eeprom->type == ixgbe_eeprom_uninitialized) {
+ eeprom->semaphore_delay = 10;
+ eeprom->type = ixgbe_flash;
+
+ eec = IXGBE_READ_REG(hw, IXGBE_EEC);
+ eeprom_size = (uint16_t)((eec & IXGBE_EEC_SIZE) >>
+ IXGBE_EEC_SIZE_SHIFT);
+ eeprom->word_size = 1 << (eeprom_size +
+ IXGBE_EEPROM_WORD_SIZE_BASE_SHIFT);
+
+ DEBUGOUT2("Eeprom params: type = %d, size = %d\n",
+ eeprom->type, eeprom->word_size);
+ }
+
+ return IXGBE_SUCCESS;
+}
+
+/**
+ * ixgbe_read_eerd_X540- Read EEPROM word using EERD
+ * @hw: pointer to hardware structure
+ * @offset: offset of word in the EEPROM to read
+ * @data: word read from the EEPROM
+ *
+ * Reads a 16 bit word from the EEPROM using the EERD register.
+ **/
+int32_t ixgbe_read_eerd_X540(struct ixgbe_hw *hw, uint16_t offset, uint16_t *data)
+{
+ int32_t status = IXGBE_SUCCESS;
+
+ DEBUGFUNC("ixgbe_read_eerd_X540");
+ if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) ==
+ IXGBE_SUCCESS)
+ status = ixgbe_read_eerd_generic(hw, offset, data);
+ else
+ status = IXGBE_ERR_SWFW_SYNC;
+
+ hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
+ return status;
+}
+
+/**
+ * ixgbe_write_eewr_X540 - Write EEPROM word using EEWR
+ * @hw: pointer to hardware structure
+ * @offset: offset of word in the EEPROM to write
+ * @data: word write to the EEPROM
+ *
+ * Write a 16 bit word to the EEPROM using the EEWR register.
+ **/
+int32_t ixgbe_write_eewr_X540(struct ixgbe_hw *hw, uint16_t offset, uint16_t data)
+{
+ int32_t status = IXGBE_SUCCESS;
+
+ DEBUGFUNC("ixgbe_write_eewr_X540");
+ if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) ==
+ IXGBE_SUCCESS)
+ status = ixgbe_write_eewr_generic(hw, offset, data);
+ else
+ status = IXGBE_ERR_SWFW_SYNC;
+
+ hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
+ return status;
+}
+
+/**
+ * ixgbe_calc_eeprom_checksum_X540 - Calculates and returns the checksum
+ *
+ * This function does not use synchronization for EERD and EEWR. It can
+ * be used internally by function which utilize ixgbe_acquire_swfw_sync_X540.
+ *
+ * @hw: pointer to hardware structure
+ **/
+uint16_t ixgbe_calc_eeprom_checksum_X540(struct ixgbe_hw *hw)
+{
+ uint16_t i;
+ uint16_t j;
+ uint16_t checksum = 0;
+ uint16_t length = 0;
+ uint16_t pointer = 0;
+ uint16_t word = 0;
+
+ /*
+ * Do not use hw->eeprom.ops.read because we do not want to take
+ * the synchronization semaphores here. Instead use
+ * ixgbe_read_eerd_generic
+ */
+
+ DEBUGFUNC("ixgbe_calc_eeprom_checksum_X540");
+
+ /* Include 0x0-0x3F in the checksum */
+ for (i = 0; i < IXGBE_EEPROM_CHECKSUM; i++) {
+ if (ixgbe_read_eerd_generic(hw, i, &word) != IXGBE_SUCCESS) {
+ DEBUGOUT("EEPROM read failed\n");
+ break;
+ }
+ checksum += word;
+ }
+
+ /*
+ * Include all data from pointers 0x3, 0x6-0xE. This excludes the
+ * FW, PHY module, and PCIe Expansion/Option ROM pointers.
+ */
+ for (i = IXGBE_PCIE_ANALOG_PTR; i < IXGBE_FW_PTR; i++) {
+ if (i == IXGBE_PHY_PTR || i == IXGBE_OPTION_ROM_PTR)
+ continue;
+
+ if (ixgbe_read_eerd_generic(hw, i, &pointer) != IXGBE_SUCCESS) {
+ DEBUGOUT("EEPROM read failed\n");
+ break;
+ }
+
+ /* Skip pointer section if the pointer is invalid. */
+ if (pointer == 0xFFFF || pointer == 0 ||
+ pointer >= hw->eeprom.word_size)
+ continue;
+
+ if (ixgbe_read_eerd_generic(hw, pointer, &length) !=
+ IXGBE_SUCCESS) {
+ DEBUGOUT("EEPROM read failed\n");
+ break;
+ }
+
+ /* Skip pointer section if length is invalid. */
+ if (length == 0xFFFF || length == 0 ||
+ (pointer + length) >= hw->eeprom.word_size)
+ continue;
+
+ for (j = pointer+1; j <= pointer+length; j++) {
+ if (ixgbe_read_eerd_generic(hw, j, &word) !=
+ IXGBE_SUCCESS) {
+ DEBUGOUT("EEPROM read failed\n");
+ break;
+ }
+ checksum += word;
+ }
+ }
+
+ checksum = (uint16_t)IXGBE_EEPROM_SUM - checksum;
+
+ return checksum;
+}
+
+/**
+ * ixgbe_validate_eeprom_checksum_X540 - Validate EEPROM checksum
+ * @hw: pointer to hardware structure
+ * @checksum_val: calculated checksum
+ *
+ * Performs checksum calculation and validates the EEPROM checksum. If the
+ * caller does not need checksum_val, the value can be NULL.
+ **/
+int32_t ixgbe_validate_eeprom_checksum_X540(struct ixgbe_hw *hw,
+ uint16_t *checksum_val)
+{
+ int32_t status;
+ uint16_t checksum;
+ uint16_t read_checksum = 0;
+
+ DEBUGFUNC("ixgbe_validate_eeprom_checksum_X540");
+
+ /*
+ * Read the first word from the EEPROM. If this times out or fails, do
+ * not continue or we could be in for a very long wait while every
+ * EEPROM read fails
+ */
+ status = hw->eeprom.ops.read(hw, 0, &checksum);
+
+ if (status != IXGBE_SUCCESS) {
+ DEBUGOUT("EEPROM read failed\n");
+ goto out;
+ }
+
+ if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) ==
+ IXGBE_SUCCESS) {
+ checksum = hw->eeprom.ops.calc_checksum(hw);
+
+ /*
+ * Do not use hw->eeprom.ops.read because we do not want to take
+ * the synchronization semaphores twice here.
+ */
+ ixgbe_read_eerd_generic(hw, IXGBE_EEPROM_CHECKSUM,
+ &read_checksum);
+
+ /*
+ * Verify read checksum from EEPROM is the same as
+ * calculated checksum
+ */
+ if (read_checksum != checksum)
+ status = IXGBE_ERR_EEPROM_CHECKSUM;
+
+ /* If the user cares, return the calculated checksum */
+ if (checksum_val)
+ *checksum_val = checksum;
+ } else {
+ status = IXGBE_ERR_SWFW_SYNC;
+ }
+
+ hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
+out:
+ return status;
+}
+
+/**
+ * ixgbe_update_eeprom_checksum_X540 - Updates the EEPROM checksum and flash
+ * @hw: pointer to hardware structure
+ *
+ * After writing EEPROM to shadow RAM using EEWR register, software calculates
+ * checksum and updates the EEPROM and instructs the hardware to update
+ * the flash.
+ **/
+int32_t ixgbe_update_eeprom_checksum_X540(struct ixgbe_hw *hw)
+{
+ int32_t status;
+ uint16_t checksum;
+
+ DEBUGFUNC("ixgbe_update_eeprom_checksum_X540");
+
+ /*
+ * Read the first word from the EEPROM. If this times out or fails, do
+ * not continue or we could be in for a very long wait while every
+ * EEPROM read fails
+ */
+ status = hw->eeprom.ops.read(hw, 0, &checksum);
+
+ if (status != IXGBE_SUCCESS)
+ DEBUGOUT("EEPROM read failed\n");
+
+ if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) ==
+ IXGBE_SUCCESS) {
+ checksum = hw->eeprom.ops.calc_checksum(hw);
+
+ /*
+ * Do not use hw->eeprom.ops.write because we do not want to
+ * take the synchronization semaphores twice here.
+ */
+ status = ixgbe_write_eewr_generic(hw, IXGBE_EEPROM_CHECKSUM,
+ checksum);
+
+ if (status == IXGBE_SUCCESS)
+ status = ixgbe_update_flash_X540(hw);
+ else
+ status = IXGBE_ERR_SWFW_SYNC;
+ }
+
+ hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
+
+ return status;
+}
+
+/**
+ * ixgbe_update_flash_X540 - Instruct HW to copy EEPROM to Flash device
+ * @hw: pointer to hardware structure
+ *
+ * Set FLUP (bit 23) of the EEC register to instruct Hardware to copy
+ * EEPROM from shadow RAM to the flash device.
+ **/
+int32_t ixgbe_update_flash_X540(struct ixgbe_hw *hw)
+{
+ uint32_t flup;
+ int32_t status = IXGBE_ERR_EEPROM;
+
+ DEBUGFUNC("ixgbe_update_flash_X540");
+
+ status = ixgbe_poll_flash_update_done_X540(hw);
+ if (status == IXGBE_ERR_EEPROM) {
+ DEBUGOUT("Flash update time out\n");
+ goto out;
+ }
+
+ flup = IXGBE_READ_REG(hw, IXGBE_EEC) | IXGBE_EEC_FLUP;
+ IXGBE_WRITE_REG(hw, IXGBE_EEC, flup);
+
+ status = ixgbe_poll_flash_update_done_X540(hw);
+ if (status == IXGBE_SUCCESS)
+ DEBUGOUT("Flash update complete\n");
+ else
+ DEBUGOUT("Flash update time out\n");
+
+ if (hw->revision_id == 0) {
+ flup = IXGBE_READ_REG(hw, IXGBE_EEC);
+
+ if (flup & IXGBE_EEC_SEC1VAL) {
+ flup |= IXGBE_EEC_FLUP;
+ IXGBE_WRITE_REG(hw, IXGBE_EEC, flup);
+ }
+
+ status = ixgbe_poll_flash_update_done_X540(hw);
+ if (status == IXGBE_SUCCESS)
+ DEBUGOUT("Flash update complete\n");
+ else
+ DEBUGOUT("Flash update time out\n");
+ }
+out:
+ return status;
+}
+
+/**
+ * ixgbe_poll_flash_update_done_X540 - Poll flash update status
+ * @hw: pointer to hardware structure
+ *
+ * Polls the FLUDONE (bit 26) of the EEC Register to determine when the
+ * flash update is done.
+ **/
+int32_t ixgbe_poll_flash_update_done_X540(struct ixgbe_hw *hw)
+{
+ uint32_t i;
+ uint32_t reg;
+ int32_t status = IXGBE_ERR_EEPROM;
+
+ DEBUGFUNC("ixgbe_poll_flash_update_done_X540");
+
+ for (i = 0; i < IXGBE_FLUDONE_ATTEMPTS; i++) {
+ reg = IXGBE_READ_REG(hw, IXGBE_EEC);
+ if (reg & IXGBE_EEC_FLUDONE) {
+ status = IXGBE_SUCCESS;
+ break;
+ }
+ usec_delay(5);
+ }
+ return status;
+}
+
+/**
+ * ixgbe_acquire_swfw_sync_X540 - Acquire SWFW semaphore
+ * @hw: pointer to hardware structure
+ * @mask: Mask to specify which semaphore to acquire
+ *
+ * Acquires the SWFW semaphore thought the SW_FW_SYNC register for
+ * the specified function (CSR, PHY0, PHY1, NVM, Flash)
+ **/
+int32_t ixgbe_acquire_swfw_sync_X540(struct ixgbe_hw *hw, uint16_t mask)
+{
+ uint32_t swfw_sync;
+ uint32_t swmask = mask;
+ uint32_t fwmask = mask << 5;
+ uint32_t hwmask = 0;
+ uint32_t timeout = 200;
+ uint32_t i;
+ int32_t ret_val = IXGBE_SUCCESS;
+
+ DEBUGFUNC("ixgbe_acquire_swfw_sync_X540");
+
+ if (swmask == IXGBE_GSSR_EEP_SM)
+ hwmask = IXGBE_GSSR_FLASH_SM;
+
+ /* SW only mask doesn't have FW bit pair */
+ if (swmask == IXGBE_GSSR_SW_MNG_SM)
+ fwmask = 0;
+
+ for (i = 0; i < timeout; i++) {
+ /*
+ * SW NVM semaphore bit is used for access to all
+ * SW_FW_SYNC bits (not just NVM)
+ */
+ if (ixgbe_get_swfw_sync_semaphore(hw)) {
+ ret_val = IXGBE_ERR_SWFW_SYNC;
+ goto out;
+ }
+
+ swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC);
+ if (!(swfw_sync & (fwmask | swmask | hwmask))) {
+ swfw_sync |= swmask;
+ IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC, swfw_sync);
+ ixgbe_release_swfw_sync_semaphore(hw);
+ msec_delay(5);
+ goto out;
+ } else {
+ /*
+ * Firmware currently using resource (fwmask), hardware
+ * currently using resource (hwmask), or other software
+ * thread currently using resource (swmask)
+ */
+ ixgbe_release_swfw_sync_semaphore(hw);
+ msec_delay(5);
+ }
+ }
+
+ /* Failed to get SW only semaphore */
+ if (swmask == IXGBE_GSSR_SW_MNG_SM) {
+ ret_val = IXGBE_ERR_SWFW_SYNC;
+ goto out;
+ }
+
+ /* If the resource is not released by the FW/HW the SW can assume that
+ * the FW/HW malfunctions. In that case the SW should sets the SW bit(s)
+ * of the requested resource(s) while ignoring the corresponding FW/HW
+ * bits in the SW_FW_SYNC register.
+ */
+ swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC);
+ if (swfw_sync & (fwmask | hwmask)) {
+ if (ixgbe_get_swfw_sync_semaphore(hw)) {
+ ret_val = IXGBE_ERR_SWFW_SYNC;
+ goto out;
+ }
+
+ swfw_sync |= swmask;
+ IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC, swfw_sync);
+ ixgbe_release_swfw_sync_semaphore(hw);
+ msec_delay(5);
+ }
+
+out:
+ return ret_val;
+}
+
+/**
+ * ixgbe_release_swfw_sync_X540 - Release SWFW semaphore
+ * @hw: pointer to hardware structure
+ * @mask: Mask to specify which semaphore to release
+ *
+ * Releases the SWFW semaphore through the SW_FW_SYNC register
+ * for the specified function (CSR, PHY0, PHY1, EVM, Flash)
+ **/
+void ixgbe_release_swfw_sync_X540(struct ixgbe_hw *hw, uint16_t mask)
+{
+ uint32_t swfw_sync;
+ uint32_t swmask = mask;
+
+ DEBUGFUNC("ixgbe_release_swfw_sync_X540");
+
+ ixgbe_get_swfw_sync_semaphore(hw);
+
+ swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC);
+ swfw_sync &= ~swmask;
+ IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC, swfw_sync);
+
+ ixgbe_release_swfw_sync_semaphore(hw);
+ msec_delay(5);
+}
+
+/**
+ * ixgbe_get_nvm_semaphore - Get hardware semaphore
+ * @hw: pointer to hardware structure
+ *
+ * Sets the hardware semaphores so SW/FW can gain control of shared resources
+ **/
+int32_t ixgbe_get_swfw_sync_semaphore(struct ixgbe_hw *hw)
+{
+ int32_t status = IXGBE_ERR_EEPROM;
+ uint32_t timeout = 2000;
+ uint32_t i;
+ uint32_t swsm;
+
+ DEBUGFUNC("ixgbe_get_swfw_sync_semaphore");
+
+ /* Get SMBI software semaphore between device drivers first */
+ for (i = 0; i < timeout; i++) {
+ /*
+ * If the SMBI bit is 0 when we read it, then the bit will be
+ * set and we have the semaphore
+ */
+ swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
+ if (!(swsm & IXGBE_SWSM_SMBI)) {
+ status = IXGBE_SUCCESS;
+ break;
+ }
+ usec_delay(50);
+ }
+
+ /* Now get the semaphore between SW/FW through the REGSMP bit */
+ if (status == IXGBE_SUCCESS) {
+ for (i = 0; i < timeout; i++) {
+ swsm = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC);
+ if (!(swsm & IXGBE_SWFW_REGSMP))
+ break;
+
+ usec_delay(50);
+ }
+
+ /*
+ * Release semaphores and return error if SW NVM semaphore
+ * was not granted because we don't have access to the EEPROM
+ */
+ if (i >= timeout) {
+ DEBUGOUT("REGSMP Software NVM semaphore not "
+ "granted.\n");
+ ixgbe_release_swfw_sync_semaphore(hw);
+ status = IXGBE_ERR_EEPROM;
+ }
+ } else {
+ DEBUGOUT("Software semaphore SMBI between device drivers "
+ "not granted.\n");
+ }
+
+ return status;
+}
+
+/**
+ * ixgbe_release_nvm_semaphore - Release hardware semaphore
+ * @hw: pointer to hardware structure
+ *
+ * This function clears hardware semaphore bits.
+ **/
+void ixgbe_release_swfw_sync_semaphore(struct ixgbe_hw *hw)
+{
+ uint32_t swsm;
+
+ DEBUGFUNC("ixgbe_release_swfw_sync_semaphore");
+
+ /* Release both semaphores by writing 0 to the bits REGSMP and SMBI */
+
+ swsm = IXGBE_READ_REG(hw, IXGBE_SWSM);
+ swsm &= ~IXGBE_SWSM_SMBI;
+ IXGBE_WRITE_REG(hw, IXGBE_SWSM, swsm);
+
+ swsm = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC);
+ swsm &= ~IXGBE_SWFW_REGSMP;
+ IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC, swsm);
+
+ IXGBE_WRITE_FLUSH(hw);
+}
+
+/**
+ * ixgbe_blink_led_start_X540 - Blink LED based on index.
+ * @hw: pointer to hardware structure
+ * @index: led number to blink
+ *
+ * Devices that implement the version 2 interface:
+ * X540
+ **/
+int32_t ixgbe_blink_led_start_X540(struct ixgbe_hw *hw, uint32_t index)
+{
+ uint32_t macc_reg;
+ uint32_t ledctl_reg;
+ ixgbe_link_speed speed;
+ int link_up;
+
+ DEBUGFUNC("ixgbe_blink_led_start_X540");
+
+ /*
+ * Link should be up in order for the blink bit in the LED control
+ * register to work. Force link and speed in the MAC if link is down.
+ * This will be reversed when we stop the blinking.
+ */
+ hw->mac.ops.check_link(hw, &speed, &link_up, FALSE);
+ if (link_up == FALSE) {
+ macc_reg = IXGBE_READ_REG(hw, IXGBE_MACC);
+ macc_reg |= IXGBE_MACC_FLU | IXGBE_MACC_FSV_10G | IXGBE_MACC_FS;
+ IXGBE_WRITE_REG(hw, IXGBE_MACC, macc_reg);
+ }
+ /* Set the LED to LINK_UP + BLINK. */
+ ledctl_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
+ ledctl_reg &= ~IXGBE_LED_MODE_MASK(index);
+ ledctl_reg |= IXGBE_LED_BLINK(index);
+ IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, ledctl_reg);
+ IXGBE_WRITE_FLUSH(hw);
+
+ return IXGBE_SUCCESS;
+}
+
+/**
+ * ixgbe_blink_led_stop_X540 - Stop blinking LED based on index.
+ * @hw: pointer to hardware structure
+ * @index: led number to stop blinking
+ *
+ * Devices that implement the version 2 interface:
+ * X540
+ **/
+int32_t ixgbe_blink_led_stop_X540(struct ixgbe_hw *hw, uint32_t index)
+{
+ uint32_t macc_reg;
+ uint32_t ledctl_reg;
+
+ DEBUGFUNC("ixgbe_blink_led_stop_X540");
+
+ /* Restore the LED to its default value. */
+ ledctl_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
+ ledctl_reg &= ~IXGBE_LED_MODE_MASK(index);
+ ledctl_reg |= IXGBE_LED_LINK_ACTIVE << IXGBE_LED_MODE_SHIFT(index);
+ ledctl_reg &= ~IXGBE_LED_BLINK(index);
+ IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, ledctl_reg);
+
+ /* Unforce link and speed in the MAC. */
+ macc_reg = IXGBE_READ_REG(hw, IXGBE_MACC);
+ macc_reg &= ~(IXGBE_MACC_FLU | IXGBE_MACC_FSV_10G | IXGBE_MACC_FS);
+ IXGBE_WRITE_REG(hw, IXGBE_MACC, macc_reg);
+ IXGBE_WRITE_FLUSH(hw);
+
+ return IXGBE_SUCCESS;
+}