diff options
author | Mike Belopuhov <mikeb@cvs.openbsd.org> | 2016-11-17 19:26:58 +0000 |
---|---|---|
committer | Mike Belopuhov <mikeb@cvs.openbsd.org> | 2016-11-17 19:26:58 +0000 |
commit | 244408ba40a32ede2f8ad06cd569db93d55ad4c8 (patch) | |
tree | 03ef2cac6bc5f931bf27f063043fece1ba5b1ecb /sys/dev | |
parent | 9d3b4fee5e4e67b648dedafed3b2324a3bd6ee2f (diff) |
Bring in new PHY bits, some of the 82599 specific stuff becomes shared
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/pci/ixgbe.c | 585 | ||||
-rw-r--r-- | sys/dev/pci/ixgbe.h | 60 | ||||
-rw-r--r-- | sys/dev/pci/ixgbe_82598.c | 6 | ||||
-rw-r--r-- | sys/dev/pci/ixgbe_82599.c | 513 | ||||
-rw-r--r-- | sys/dev/pci/ixgbe_phy.c | 465 | ||||
-rw-r--r-- | sys/dev/pci/ixgbe_type.h | 11 | ||||
-rw-r--r-- | sys/dev/pci/ixgbe_x540.c | 12 |
7 files changed, 1289 insertions, 363 deletions
diff --git a/sys/dev/pci/ixgbe.c b/sys/dev/pci/ixgbe.c index 331be27b1b5..462c79e7458 100644 --- a/sys/dev/pci/ixgbe.c +++ b/sys/dev/pci/ixgbe.c @@ -1,8 +1,8 @@ -/* $OpenBSD: ixgbe.c,v 1.16 2016/11/17 12:21:27 mikeb Exp $ */ +/* $OpenBSD: ixgbe.c,v 1.17 2016/11/17 19:26:57 mikeb Exp $ */ /****************************************************************************** - 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 @@ -32,8 +32,8 @@ POSSIBILITY OF SUCH DAMAGE. ******************************************************************************/ -/* FreeBSD: src/sys/dev/ixgbe/ixgbe_common.c 251964 Jun 18 21:28:19 2013 UTC */ -/* FreeBSD: src/sys/dev/ixgbe/ixgbe_mbx.c 230775 Jan 30 16:42:02 2012 UTC */ +/*$FreeBSD: head/sys/dev/ixgbe/ixgbe_common.c 299200 2016-05-06 22:54:56Z pfg $*/ +/*$FreeBSD: head/sys/dev/ixgbe/ixgbe_mbx.c 299200 2016-05-06 22:54:56Z pfg $*/ #include <dev/pci/ixgbe.h> @@ -144,6 +144,8 @@ int32_t ixgbe_init_ops_generic(struct ixgbe_hw *hw) mac->ops.clear_vfta = NULL; mac->ops.set_vfta = NULL; mac->ops.init_uta_tables = NULL; + mac->ops.enable_rx = ixgbe_enable_rx_generic; + mac->ops.disable_rx = ixgbe_disable_rx_generic; /* Flow Control */ mac->ops.fc_enable = ixgbe_fc_enable_generic; @@ -175,6 +177,7 @@ bool ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw) switch (hw->phy.media_type) { case ixgbe_media_type_fiber_fixed: + case ixgbe_media_type_fiber_qsfp: case ixgbe_media_type_fiber: hw->mac.ops.check_link(hw, &speed, &link_up, FALSE); /* if link is down, assume supported */ @@ -192,7 +195,11 @@ bool ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw) switch (hw->device_id) { case IXGBE_DEV_ID_82599_T3_LOM: case IXGBE_DEV_ID_X540T: + case IXGBE_DEV_ID_X540T1: case IXGBE_DEV_ID_X540_BYPASS: + case IXGBE_DEV_ID_X550T: + case IXGBE_DEV_ID_X550T1: + case IXGBE_DEV_ID_X550EM_X_10G_T: supported = TRUE; break; default: @@ -202,9 +209,12 @@ bool ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw) break; } - ERROR_REPORT2(IXGBE_ERROR_UNSUPPORTED, + if (!supported) { + ERROR_REPORT2(IXGBE_ERROR_UNSUPPORTED, "Device %x does not support flow control autoneg", hw->device_id); + } + return supported; } @@ -248,6 +258,7 @@ int32_t ixgbe_setup_fc(struct ixgbe_hw *hw) */ switch (hw->phy.media_type) { case ixgbe_media_type_fiber_fixed: + case ixgbe_media_type_fiber_qsfp: case ixgbe_media_type_fiber: case ixgbe_media_type_backplane: reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA); @@ -323,7 +334,7 @@ int32_t ixgbe_setup_fc(struct ixgbe_hw *hw) break; } - if (hw->mac.type != ixgbe_mac_X540) { + if (hw->mac.type < ixgbe_mac_X540) { /* * Enable auto-negotiation between the MAC & PHY; * the MAC will advertise clause 37 flow control. @@ -588,7 +599,7 @@ int32_t ixgbe_clear_hw_cntrs_generic(struct ixgbe_hw *hw) } } - if (hw->mac.type == ixgbe_mac_X540) { + if (hw->mac.type == ixgbe_mac_X550 || hw->mac.type == ixgbe_mac_X540) { if (hw->phy.id == 0) ixgbe_identify_phy(hw); hw->phy.ops.read_reg(hw, IXGBE_PCRC8ECL, @@ -759,7 +770,7 @@ int32_t ixgbe_stop_adapter_generic(struct ixgbe_hw *hw) hw->adapter_stopped = TRUE; /* Disable the receive unit */ - IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, 0); + ixgbe_disable_rx(hw); /* Clear interrupt mask to stop interrupts from being generated */ IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_IRQ_CLEAR_MASK); @@ -2356,6 +2367,7 @@ void ixgbe_fc_autoneg(struct ixgbe_hw *hw) switch (hw->phy.media_type) { /* Autoneg flow control on fiber adapters */ case ixgbe_media_type_fiber_fixed: + case ixgbe_media_type_fiber_qsfp: case ixgbe_media_type_fiber: if (speed == IXGBE_LINK_SPEED_1GB_FULL) ret_val = ixgbe_fc_autoneg_fiber(hw); @@ -2473,6 +2485,9 @@ int32_t ixgbe_disable_pcie_master(struct ixgbe_hw *hw) DEBUGOUT("GIO Master Disable bit didn't clear - requesting resets\n"); hw->mac.flags |= IXGBE_FLAGS_DOUBLE_RESET_REQUIRED; + if (hw->mac.type >= ixgbe_mac_X550) + goto out; + /* * Before proceeding, make sure that the PCIe block does not have * transactions pending. @@ -2632,7 +2647,10 @@ int32_t ixgbe_enable_rx_dma_generic(struct ixgbe_hw *hw, uint32_t regval) { DEBUGFUNC("ixgbe_enable_rx_dma_generic"); - IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, regval); + if (regval & IXGBE_RXCTRL_RXEN) + ixgbe_enable_rx(hw); + else + ixgbe_disable_rx(hw); return IXGBE_SUCCESS; } @@ -2761,6 +2779,8 @@ uint16_t ixgbe_get_pcie_msix_count_generic(struct ixgbe_hw *hw) break; case ixgbe_mac_82599EB: case ixgbe_mac_X540: + case ixgbe_mac_X550: + case ixgbe_mac_X550EM_x: pcie_offset = IXGBE_PCIE_MSIX_82599_CAPS; max_msix_count = IXGBE_MAX_MSIX_VECTORS_82599; break; @@ -3224,7 +3244,7 @@ int32_t ixgbe_check_mac_link_generic(struct ixgbe_hw *hw, ixgbe_link_speed *spee } if (link_up_wait_to_complete) { - for (i = 0; i < IXGBE_LINK_UP_TIME; i++) { + for (i = 0; i < hw->mac.max_link_up_time; i++) { if (links_reg & IXGBE_LINKS_UP) { *link_up = TRUE; break; @@ -3241,17 +3261,27 @@ int32_t ixgbe_check_mac_link_generic(struct ixgbe_hw *hw, ixgbe_link_speed *spee *link_up = FALSE; } - if ((links_reg & IXGBE_LINKS_SPEED_82599) == - IXGBE_LINKS_SPEED_10G_82599) + switch (links_reg & IXGBE_LINKS_SPEED_82599) { + case IXGBE_LINKS_SPEED_10G_82599: *speed = IXGBE_LINK_SPEED_10GB_FULL; - else if ((links_reg & IXGBE_LINKS_SPEED_82599) == - IXGBE_LINKS_SPEED_1G_82599) + if (hw->mac.type >= ixgbe_mac_X550) { + if (links_reg & IXGBE_LINKS_SPEED_NON_STD) + *speed = IXGBE_LINK_SPEED_2_5GB_FULL; + } + break; + case IXGBE_LINKS_SPEED_1G_82599: *speed = IXGBE_LINK_SPEED_1GB_FULL; - else if ((links_reg & IXGBE_LINKS_SPEED_82599) == - IXGBE_LINKS_SPEED_100_82599) + break; + case IXGBE_LINKS_SPEED_100_82599: *speed = IXGBE_LINK_SPEED_100_FULL; - else + if (hw->mac.type >= ixgbe_mac_X550) { + if (links_reg & IXGBE_LINKS_SPEED_NON_STD) + *speed = IXGBE_LINK_SPEED_5GB_FULL; + } + break; + default: *speed = IXGBE_LINK_SPEED_UNKNOWN; + } return IXGBE_SUCCESS; } @@ -3274,6 +3304,115 @@ int32_t ixgbe_get_device_caps_generic(struct ixgbe_hw *hw, uint16_t *device_caps } /** + * ixgbe_host_interface_command - Issue command to manageability block + * @hw: pointer to the HW structure + * @buffer: contains the command to write and where the return status will + * be placed + * @length: length of buffer, must be multiple of 4 bytes + * @timeout: time in ms to wait for command completion + * @return_data: read and return data from the buffer (TRUE) or not (FALSE) + * Needed because FW structures are big endian and decoding of + * these fields can be 8 bit or 16 bit based on command. Decoding + * is not easily understood without making a table of commands. + * So we will leave this up to the caller to read back the data + * in these cases. + * + * Communicates with the manageability block. On success return IXGBE_SUCCESS + * else return IXGBE_ERR_HOST_INTERFACE_COMMAND. + **/ +int32_t ixgbe_host_interface_command(struct ixgbe_hw *hw, uint32_t *buffer, + uint32_t length, uint32_t timeout, + bool return_data) +{ + uint32_t hicr, i, bi, fwsts; + uint32_t hdr_size = sizeof(struct ixgbe_hic_hdr); + uint16_t buf_len; + uint16_t dword_len; + + DEBUGFUNC("ixgbe_host_interface_command"); + + if (length == 0 || length > IXGBE_HI_MAX_BLOCK_BYTE_LENGTH) { + DEBUGOUT1("Buffer length failure buffersize=%d.\n", length); + return IXGBE_ERR_HOST_INTERFACE_COMMAND; + } + /* Set bit 9 of FWSTS clearing FW reset indication */ + fwsts = IXGBE_READ_REG(hw, IXGBE_FWSTS); + IXGBE_WRITE_REG(hw, IXGBE_FWSTS, fwsts | IXGBE_FWSTS_FWRI); + + /* Check that the host interface is enabled. */ + hicr = IXGBE_READ_REG(hw, IXGBE_HICR); + if ((hicr & IXGBE_HICR_EN) == 0) { + DEBUGOUT("IXGBE_HOST_EN bit disabled.\n"); + return IXGBE_ERR_HOST_INTERFACE_COMMAND; + } + + /* Calculate length in DWORDs. We must be DWORD aligned */ + if ((length % (sizeof(uint32_t))) != 0) { + DEBUGOUT("Buffer length failure, not aligned to dword"); + return IXGBE_ERR_INVALID_ARGUMENT; + } + + dword_len = length >> 2; + + /* The device driver writes the relevant command block + * into the ram area. + */ + for (i = 0; i < dword_len; i++) + IXGBE_WRITE_REG_ARRAY(hw, IXGBE_FLEX_MNG, + i, htole32(buffer[i])); + + /* Setting this bit tells the ARC that a new command is pending. */ + IXGBE_WRITE_REG(hw, IXGBE_HICR, hicr | IXGBE_HICR_C); + + for (i = 0; i < timeout; i++) { + hicr = IXGBE_READ_REG(hw, IXGBE_HICR); + if (!(hicr & IXGBE_HICR_C)) + break; + msec_delay(1); + } + + /* Check command completion */ + if ((timeout != 0 && i == timeout) || + !(IXGBE_READ_REG(hw, IXGBE_HICR) & IXGBE_HICR_SV)) { + DEBUGOUT("Command has failed with no status valid.\n"); + return IXGBE_ERR_HOST_INTERFACE_COMMAND; + } + + if (!return_data) + return 0; + + /* Calculate length in DWORDs */ + dword_len = hdr_size >> 2; + + /* first pull in the header so we know the buffer length */ + for (bi = 0; bi < dword_len; bi++) { + buffer[bi] = letoh32(IXGBE_READ_REG_ARRAY(hw, + IXGBE_FLEX_MNG, bi)); + } + + /* If there is any thing in data position pull it in */ + buf_len = ((struct ixgbe_hic_hdr *)buffer)->buf_len; + if (buf_len == 0) + return 0; + + if (length < buf_len + hdr_size) { + DEBUGOUT("Buffer not large enough for reply message.\n"); + return IXGBE_ERR_HOST_INTERFACE_COMMAND; + } + + /* Calculate length in DWORDs, add 3 for odd lengths */ + dword_len = (buf_len + 3) >> 2; + + /* Pull in the rest of the buffer (bi is where we left off) */ + for (; bi <= dword_len; bi++) { + buffer[bi] = letoh32(IXGBE_READ_REG_ARRAY(hw, + IXGBE_FLEX_MNG, bi)); + } + + return 0; +} + +/** * ixgbe_clear_tx_pending - Clear pending TX work from the PCIe fifo * @hw: pointer to the hardware structure * @@ -3314,6 +3453,306 @@ void ixgbe_clear_tx_pending(struct ixgbe_hw *hw) IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0); } +void ixgbe_disable_rx_generic(struct ixgbe_hw *hw) +{ + uint32_t rxctrl; + + rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); + if (rxctrl & IXGBE_RXCTRL_RXEN) { + rxctrl &= ~IXGBE_RXCTRL_RXEN; + IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl); + } +} + +void ixgbe_enable_rx_generic(struct ixgbe_hw *hw) +{ + uint32_t rxctrl; + + rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); + IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, (rxctrl | IXGBE_RXCTRL_RXEN)); +} + +/** + * ixgbe_mng_present - returns TRUE when management capability is present + * @hw: pointer to hardware structure + */ +bool ixgbe_mng_present(struct ixgbe_hw *hw) +{ + uint32_t fwsm; + + if (hw->mac.type < ixgbe_mac_82599EB) + return FALSE; + + fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM); + fwsm &= IXGBE_FWSM_MODE_MASK; + return fwsm == IXGBE_FWSM_FW_MODE_PT; +} + +/** + * ixgbe_mng_enabled - Is the manageability engine enabled? + * @hw: pointer to hardware structure + * + * Returns TRUE if the manageability engine is enabled. + **/ +bool ixgbe_mng_enabled(struct ixgbe_hw *hw) +{ + uint32_t fwsm, manc, factps; + + fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM); + if ((fwsm & IXGBE_FWSM_MODE_MASK) != IXGBE_FWSM_FW_MODE_PT) + return FALSE; + + manc = IXGBE_READ_REG(hw, IXGBE_MANC); + if (!(manc & IXGBE_MANC_RCV_TCO_EN)) + return FALSE; + + if (hw->mac.type <= ixgbe_mac_X540) { + factps = IXGBE_READ_REG(hw, IXGBE_FACTPS); + if (factps & IXGBE_FACTPS_MNGCG) + return FALSE; + } + + return TRUE; +} + +/** + * ixgbe_setup_mac_link_multispeed_fiber - Set MAC link speed + * @hw: pointer to hardware structure + * @speed: new link speed + * @autoneg_wait_to_complete: TRUE when waiting for completion is needed + * + * Set the link speed in the MAC and/or PHY register and restarts link. + **/ +int32_t ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw, + ixgbe_link_speed speed, + bool autoneg_wait_to_complete) +{ + ixgbe_link_speed link_speed = IXGBE_LINK_SPEED_UNKNOWN; + ixgbe_link_speed highest_link_speed = IXGBE_LINK_SPEED_UNKNOWN; + int32_t status = IXGBE_SUCCESS; + uint32_t speedcnt = 0; + uint32_t i = 0; + bool autoneg, link_up = FALSE; + + DEBUGFUNC("ixgbe_setup_mac_link_multispeed_fiber"); + + /* Mask off requested but non-supported speeds */ + if (!hw->mac.ops.get_link_capabilities) + return IXGBE_NOT_IMPLEMENTED; + status = hw->mac.ops.get_link_capabilities(hw, &link_speed, &autoneg); + if (status != IXGBE_SUCCESS) + return status; + + speed &= link_speed; + + /* Try each speed one by one, highest priority first. We do this in + * software because 10Gb fiber doesn't support speed autonegotiation. + */ + if (speed & IXGBE_LINK_SPEED_10GB_FULL) { + speedcnt++; + highest_link_speed = IXGBE_LINK_SPEED_10GB_FULL; + + /* If we already have link at this speed, just jump out */ + status = ixgbe_check_link(hw, &link_speed, &link_up, FALSE); + if (status != IXGBE_SUCCESS) + return status; + + if ((link_speed == IXGBE_LINK_SPEED_10GB_FULL) && link_up) + goto out; + + /* Set the module link speed */ + switch (hw->phy.media_type) { + case ixgbe_media_type_fiber_fixed: + case ixgbe_media_type_fiber: + if (hw->mac.ops.set_rate_select_speed) + hw->mac.ops.set_rate_select_speed(hw, + IXGBE_LINK_SPEED_10GB_FULL); + break; + case ixgbe_media_type_fiber_qsfp: + /* QSFP module automatically detects MAC link speed */ + break; + default: + DEBUGOUT("Unexpected media type.\n"); + break; + } + + /* Allow module to change analog characteristics (1G->10G) */ + msec_delay(40); + + if (!hw->mac.ops.setup_mac_link) + return IXGBE_NOT_IMPLEMENTED; + status = hw->mac.ops.setup_mac_link(hw, + IXGBE_LINK_SPEED_10GB_FULL, + autoneg_wait_to_complete); + if (status != IXGBE_SUCCESS) + return status; + + /* Flap the Tx laser if it has not already been done */ + ixgbe_flap_tx_laser(hw); + + /* Wait for the controller to acquire link. Per IEEE 802.3ap, + * Section 73.10.2, we may have to wait up to 500ms if KR is + * attempted. 82599 uses the same timing for 10g SFI. + */ + for (i = 0; i < 5; i++) { + /* Wait for the link partner to also set speed */ + msec_delay(100); + + /* If we have link, just jump out */ + status = ixgbe_check_link(hw, &link_speed, + &link_up, FALSE); + if (status != IXGBE_SUCCESS) + return status; + + if (link_up) + goto out; + } + } + + if (speed & IXGBE_LINK_SPEED_1GB_FULL) { + speedcnt++; + if (highest_link_speed == IXGBE_LINK_SPEED_UNKNOWN) + highest_link_speed = IXGBE_LINK_SPEED_1GB_FULL; + + /* If we already have link at this speed, just jump out */ + status = ixgbe_check_link(hw, &link_speed, &link_up, FALSE); + if (status != IXGBE_SUCCESS) + return status; + + if ((link_speed == IXGBE_LINK_SPEED_1GB_FULL) && link_up) + goto out; + + /* Set the module link speed */ + switch (hw->phy.media_type) { + case ixgbe_media_type_fiber_fixed: + case ixgbe_media_type_fiber: + if (hw->mac.ops.set_rate_select_speed) + hw->mac.ops.set_rate_select_speed(hw, + IXGBE_LINK_SPEED_1GB_FULL); + break; + case ixgbe_media_type_fiber_qsfp: + /* QSFP module automatically detects link speed */ + break; + default: + DEBUGOUT("Unexpected media type.\n"); + break; + } + + /* Allow module to change analog characteristics (10G->1G) */ + msec_delay(40); + + if (!hw->mac.ops.setup_mac_link) + return IXGBE_NOT_IMPLEMENTED; + status = hw->mac.ops.setup_mac_link(hw, + IXGBE_LINK_SPEED_1GB_FULL, + autoneg_wait_to_complete); + if (status != IXGBE_SUCCESS) + return status; + + /* Flap the Tx laser if it has not already been done */ + ixgbe_flap_tx_laser(hw); + + /* Wait for the link partner to also set speed */ + msec_delay(100); + + /* If we have link, just jump out */ + status = ixgbe_check_link(hw, &link_speed, &link_up, FALSE); + if (status != IXGBE_SUCCESS) + return status; + + if (link_up) + goto out; + } + + /* We didn't get link. Configure back to the highest speed we tried, + * (if there was more than one). We call ourselves back with just the + * single highest speed that the user requested. + */ + if (speedcnt > 1) + status = ixgbe_setup_mac_link_multispeed_fiber(hw, + highest_link_speed, + autoneg_wait_to_complete); + +out: + /* Set autoneg_advertised value based on input link speed */ + hw->phy.autoneg_advertised = 0; + + if (speed & IXGBE_LINK_SPEED_10GB_FULL) + hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_10GB_FULL; + + if (speed & IXGBE_LINK_SPEED_1GB_FULL) + hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL; + + return status; +} + +/** + * ixgbe_set_soft_rate_select_speed - Set module link speed + * @hw: pointer to hardware structure + * @speed: link speed to set + * + * Set module link speed via the soft rate select. + */ +void ixgbe_set_soft_rate_select_speed(struct ixgbe_hw *hw, + ixgbe_link_speed speed) +{ + int32_t status; + uint8_t rs, eeprom_data; + + switch (speed) { + case IXGBE_LINK_SPEED_10GB_FULL: + /* one bit mask same as setting on */ + rs = IXGBE_SFF_SOFT_RS_SELECT_10G; + break; + case IXGBE_LINK_SPEED_1GB_FULL: + rs = IXGBE_SFF_SOFT_RS_SELECT_1G; + break; + default: + DEBUGOUT("Invalid fixed module speed\n"); + return; + } + + /* Set RS0 */ + status = hw->phy.ops.read_i2c_byte(hw, IXGBE_SFF_SFF_8472_OSCB, + IXGBE_I2C_EEPROM_DEV_ADDR2, + &eeprom_data); + if (status) { + DEBUGOUT("Failed to read Rx Rate Select RS0\n"); + goto out; + } + + eeprom_data = (eeprom_data & ~IXGBE_SFF_SOFT_RS_SELECT_MASK) | rs; + + status = hw->phy.ops.write_i2c_byte(hw, IXGBE_SFF_SFF_8472_OSCB, + IXGBE_I2C_EEPROM_DEV_ADDR2, + eeprom_data); + if (status) { + DEBUGOUT("Failed to write Rx Rate Select RS0\n"); + goto out; + } + + /* Set RS1 */ + status = hw->phy.ops.read_i2c_byte(hw, IXGBE_SFF_SFF_8472_ESCB, + IXGBE_I2C_EEPROM_DEV_ADDR2, + &eeprom_data); + if (status) { + DEBUGOUT("Failed to read Rx Rate Select RS1\n"); + goto out; + } + + eeprom_data = (eeprom_data & ~IXGBE_SFF_SOFT_RS_SELECT_MASK) | rs; + + status = hw->phy.ops.write_i2c_byte(hw, IXGBE_SFF_SFF_8472_ESCB, + IXGBE_I2C_EEPROM_DEV_ADDR2, + eeprom_data); + if (status) { + DEBUGOUT("Failed to write Rx Rate Select RS1\n"); + goto out; + } +out: + return; +} + /* MAC Operations */ /** @@ -3334,6 +3773,11 @@ int32_t ixgbe_init_shared_code(struct ixgbe_hw *hw) DEBUGFUNC("ixgbe_init_shared_code"); + /* + * Set the mac type + */ + ixgbe_set_mac_type(hw); + switch (hw->mac.type) { case ixgbe_mac_82598EB: status = ixgbe_init_ops_82598(hw); @@ -3348,11 +3792,102 @@ int32_t ixgbe_init_shared_code(struct ixgbe_hw *hw) status = IXGBE_ERR_DEVICE_NOT_SUPPORTED; break; } + hw->mac.max_link_up_time = IXGBE_LINK_UP_TIME; return status; } /** + * ixgbe_set_mac_type - Sets MAC type + * @hw: pointer to the HW structure + * + * This function sets the mac type of the adapter based on the + * vendor ID and device ID stored in the hw structure. + **/ +int32_t ixgbe_set_mac_type(struct ixgbe_hw *hw) +{ + int32_t ret_val = IXGBE_SUCCESS; + + DEBUGFUNC("ixgbe_set_mac_type\n"); + + if (hw->vendor_id != IXGBE_INTEL_VENDOR_ID) + return IXGBE_ERR_DEVICE_NOT_SUPPORTED; + + switch (hw->device_id) { + case IXGBE_DEV_ID_82598: + case IXGBE_DEV_ID_82598_BX: + case IXGBE_DEV_ID_82598AF_SINGLE_PORT: + case IXGBE_DEV_ID_82598AF_DUAL_PORT: + case IXGBE_DEV_ID_82598AT: + case IXGBE_DEV_ID_82598AT2: + case IXGBE_DEV_ID_82598AT_DUAL_PORT: + case IXGBE_DEV_ID_82598EB_CX4: + case IXGBE_DEV_ID_82598_CX4_DUAL_PORT: + case IXGBE_DEV_ID_82598_DA_DUAL_PORT: + case IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM: + case IXGBE_DEV_ID_82598EB_XF_LR: + case IXGBE_DEV_ID_82598EB_SFP_LOM: + hw->mac.type = ixgbe_mac_82598EB; + break; + case IXGBE_DEV_ID_82599_KX4: + case IXGBE_DEV_ID_82599_KX4_MEZZ: + case IXGBE_DEV_ID_82599_XAUI_LOM: + case IXGBE_DEV_ID_82599_COMBO_BACKPLANE: + case IXGBE_DEV_ID_82599_KR: + case IXGBE_DEV_ID_82599_SFP: + case IXGBE_DEV_ID_82599_BACKPLANE_FCOE: + case IXGBE_DEV_ID_82599_SFP_FCOE: + case IXGBE_DEV_ID_82599_SFP_EM: + case IXGBE_DEV_ID_82599_SFP_SF2: + case IXGBE_DEV_ID_82599_SFP_SF_QP: + case IXGBE_DEV_ID_82599_QSFP_SF_QP: + case IXGBE_DEV_ID_82599EN_SFP: + case IXGBE_DEV_ID_82599_CX4: + case IXGBE_DEV_ID_82599_BYPASS: + case IXGBE_DEV_ID_82599_T3_LOM: + hw->mac.type = ixgbe_mac_82599EB; + break; + case IXGBE_DEV_ID_82599_VF: + case IXGBE_DEV_ID_82599_VF_HV: + hw->mac.type = ixgbe_mac_82599_vf; + break; + case IXGBE_DEV_ID_X540_VF: + case IXGBE_DEV_ID_X540_VF_HV: + hw->mac.type = ixgbe_mac_X540_vf; + break; + case IXGBE_DEV_ID_X540T: + case IXGBE_DEV_ID_X540T1: + case IXGBE_DEV_ID_X540_BYPASS: + hw->mac.type = ixgbe_mac_X540; + break; + case IXGBE_DEV_ID_X550T: + case IXGBE_DEV_ID_X550T1: + hw->mac.type = ixgbe_mac_X550; + break; + case IXGBE_DEV_ID_X550EM_X_KX4: + case IXGBE_DEV_ID_X550EM_X_KR: + case IXGBE_DEV_ID_X550EM_X_10G_T: + case IXGBE_DEV_ID_X550EM_X_1G_T: + case IXGBE_DEV_ID_X550EM_X_SFP: + hw->mac.type = ixgbe_mac_X550EM_x; + break; + case IXGBE_DEV_ID_X550_VF: + case IXGBE_DEV_ID_X550_VF_HV: + hw->mac.type = ixgbe_mac_X550_vf; + break; + case IXGBE_DEV_ID_X550EM_X_VF: + case IXGBE_DEV_ID_X550EM_X_VF_HV: + hw->mac.type = ixgbe_mac_X550EM_x_vf; + break; + default: + ret_val = IXGBE_ERR_DEVICE_NOT_SUPPORTED; + break; + } + + return ret_val; +} + +/** * ixgbe_init_hw - Initialize the hardware * @hw: pointer to hardware structure * @@ -3508,6 +4043,18 @@ int32_t ixgbe_reset_pipeline(struct ixgbe_hw *hw) return IXGBE_NOT_IMPLEMENTED; } +void ixgbe_disable_rx(struct ixgbe_hw *hw) +{ + if (hw->mac.ops.disable_rx) + hw->mac.ops.disable_rx(hw); +} + +void ixgbe_enable_rx(struct ixgbe_hw *hw) +{ + if (hw->mac.ops.enable_rx) + hw->mac.ops.enable_rx(hw); +} + /* * MBX: Mailbox handling */ @@ -3852,6 +4399,8 @@ 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_X550: + case ixgbe_mac_X550EM_x: case ixgbe_mac_X540: vflre = IXGBE_READ_REG(hw, IXGBE_VFLREC(reg_offset)); break; @@ -3983,6 +4532,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 && + hw->mac.type != ixgbe_mac_X550 && + hw->mac.type != ixgbe_mac_X550EM_x && hw->mac.type != ixgbe_mac_X540) return; diff --git a/sys/dev/pci/ixgbe.h b/sys/dev/pci/ixgbe.h index 68b855274f7..abef797ceea 100644 --- a/sys/dev/pci/ixgbe.h +++ b/sys/dev/pci/ixgbe.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ixgbe.h,v 1.23 2016/09/25 14:58:00 fcambus Exp $ */ +/* $OpenBSD: ixgbe.h,v 1.24 2016/11/17 19:26:57 mikeb Exp $ */ /****************************************************************************** @@ -151,8 +151,8 @@ extern void ixgbe_write_pci_cfg(struct ixgbe_hw *, uint32_t, uint16_t); bus_space_write_4(((struct ixgbe_osdep *)(a)->back)->os_memt, \ ((struct ixgbe_osdep *)(a)->back)->os_memh, (reg + ((offset) << 2)), value) +/* MAC Operations */ uint16_t ixgbe_get_pcie_msix_count_generic(struct ixgbe_hw *hw); - int32_t ixgbe_init_ops_generic(struct ixgbe_hw *hw); int32_t ixgbe_init_hw_generic(struct ixgbe_hw *hw); int32_t ixgbe_start_hw_generic(struct ixgbe_hw *hw); @@ -189,8 +189,6 @@ int32_t ixgbe_init_rx_addrs_generic(struct ixgbe_hw *hw); int32_t ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw, uint8_t *mc_addr_list, uint32_t mc_addr_count, ixgbe_mc_addr_itr func, bool clear); -int32_t ixgbe_update_uc_addr_list_generic(struct ixgbe_hw *hw, uint8_t *addr_list, - uint32_t addr_count, ixgbe_mc_addr_itr func); int32_t ixgbe_enable_mc_generic(struct ixgbe_hw *hw); int32_t ixgbe_disable_mc_generic(struct ixgbe_hw *hw); int32_t ixgbe_enable_rx_dma_generic(struct ixgbe_hw *hw, uint32_t regval); @@ -209,9 +207,6 @@ int32_t ixgbe_disable_pcie_master(struct ixgbe_hw *hw); int32_t ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, uint32_t index); int32_t ixgbe_blink_led_stop_generic(struct ixgbe_hw *hw, uint32_t index); -int32_t ixgbe_get_san_mac_addr_generic(struct ixgbe_hw *hw, uint8_t *san_mac_addr); -int32_t ixgbe_set_san_mac_addr_generic(struct ixgbe_hw *hw, uint8_t *san_mac_addr); - int32_t ixgbe_set_vmdq_generic(struct ixgbe_hw *hw, uint32_t rar, uint32_t vmdq); int32_t ixgbe_clear_vmdq_generic(struct ixgbe_hw *hw, uint32_t rar, uint32_t vmdq); int32_t ixgbe_insert_mac_addr_generic(struct ixgbe_hw *hw, uint8_t *addr, uint32_t vmdq); @@ -224,20 +219,49 @@ int32_t ixgbe_clear_vfta_generic(struct ixgbe_hw *hw); int32_t ixgbe_check_mac_link_generic(struct ixgbe_hw *hw, ixgbe_link_speed *speed, - bool *link_up, bool link_up_wait_to_complete); - -int32_t ixgbe_get_device_caps_generic(struct ixgbe_hw *hw, uint16_t *device_caps); -void ixgbe_enable_relaxed_ordering_gen2(struct ixgbe_hw *hw); + bool *link_up, + bool link_up_wait_to_complete); + +int32_t ixgbe_get_device_caps_generic(struct ixgbe_hw *hw, + uint16_t *device_caps); +int32_t ixgbe_host_interface_command(struct ixgbe_hw *hw, uint32_t *buffer, + uint32_t length, uint32_t timeout, + bool return_data); void ixgbe_clear_tx_pending(struct ixgbe_hw *hw); -/* MAC Operations */ +bool ixgbe_mng_present(struct ixgbe_hw *hw); +bool ixgbe_mng_enabled(struct ixgbe_hw *hw); + +void ixgbe_disable_rx_generic(struct ixgbe_hw *hw); +void ixgbe_enable_rx_generic(struct ixgbe_hw *hw); +int32_t ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw, + ixgbe_link_speed speed, + bool autoneg_wait_to_complete); +void ixgbe_set_soft_rate_select_speed(struct ixgbe_hw *hw, + ixgbe_link_speed speed); + int32_t ixgbe_init_shared_code(struct ixgbe_hw *hw); + +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); +int32_t ixgbe_init_ops_X550(struct ixgbe_hw *hw); +int32_t ixgbe_init_ops_X550EM(struct ixgbe_hw *hw); + +int32_t ixgbe_set_mac_type(struct ixgbe_hw *hw); int32_t ixgbe_init_hw(struct ixgbe_hw *hw); enum ixgbe_media_type ixgbe_get_media_type(struct ixgbe_hw *hw); int32_t ixgbe_identify_phy(struct ixgbe_hw *hw); +void ixgbe_flap_tx_laser(struct ixgbe_hw *hw); +int32_t ixgbe_setup_link(struct ixgbe_hw *hw, ixgbe_link_speed speed, + bool autoneg_wait_to_complete); +int32_t ixgbe_setup_mac_link(struct ixgbe_hw *hw, ixgbe_link_speed speed, + bool autoneg_wait_to_complete); int32_t ixgbe_check_link(struct ixgbe_hw *hw, ixgbe_link_speed *speed, bool *link_up, bool link_up_wait_to_complete); -void ixgbe_flap_tx_laser(struct ixgbe_hw *hw); +int32_t ixgbe_get_link_capabilities(struct ixgbe_hw *hw, ixgbe_link_speed *speed, + bool *autoneg); + int32_t ixgbe_set_rar(struct ixgbe_hw *hw, uint32_t index, uint8_t *addr, uint32_t vmdq, uint32_t enable_addr); int32_t ixgbe_set_vmdq(struct ixgbe_hw *hw, uint32_t rar, uint32_t vmdq); @@ -250,9 +274,8 @@ int32_t ixgbe_reset_pipeline(struct ixgbe_hw *hw); void ixgbe_add_uc_addr(struct ixgbe_hw *hw, uint8_t *addr, uint32_t vmdq); void ixgbe_set_mta(struct ixgbe_hw *hw, uint8_t *mc_addr); -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); +void ixgbe_disable_rx(struct ixgbe_hw *hw); +void ixgbe_enable_rx(struct ixgbe_hw *hw); /* PHY */ int32_t ixgbe_init_phy_ops_generic(struct ixgbe_hw *hw); @@ -276,6 +299,7 @@ int32_t ixgbe_setup_phy_link_speed_generic(struct ixgbe_hw *hw, int32_t ixgbe_get_copper_link_capabilities_generic(struct ixgbe_hw *hw, ixgbe_link_speed *speed, bool *autoneg); +int32_t ixgbe_check_reset_blocked(struct ixgbe_hw *hw); /* PHY specific */ int32_t ixgbe_check_phy_link_tnx(struct ixgbe_hw *hw, @@ -288,8 +312,12 @@ int32_t ixgbe_get_phy_firmware_version_generic(struct ixgbe_hw *hw, uint16_t *firmware_version); int32_t ixgbe_reset_phy_nl(struct ixgbe_hw *hw); +bool ixgbe_is_sfp(struct ixgbe_hw *hw); +int32_t ixgbe_set_copper_phy_power(struct ixgbe_hw *hw, bool on); int32_t ixgbe_identify_module_generic(struct ixgbe_hw *hw); int32_t ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw); +int32_t ixgbe_get_supported_phy_sfp_layer_generic(struct ixgbe_hw *hw); +int32_t ixgbe_identify_qsfp_module_generic(struct ixgbe_hw *hw); int32_t ixgbe_get_sfp_init_sequence_offsets(struct ixgbe_hw *hw, uint16_t *list_offset, uint16_t *data_offset); diff --git a/sys/dev/pci/ixgbe_82598.c b/sys/dev/pci/ixgbe_82598.c index 13c2378ed11..a486842d8e7 100644 --- a/sys/dev/pci/ixgbe_82598.c +++ b/sys/dev/pci/ixgbe_82598.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ixgbe_82598.c,v 1.14 2016/11/17 13:12:03 mikeb Exp $ */ +/* $OpenBSD: ixgbe_82598.c,v 1.15 2016/11/17 19:26:57 mikeb Exp $ */ /****************************************************************************** @@ -666,7 +666,7 @@ int32_t ixgbe_check_mac_link_82598(struct ixgbe_hw *hw, hw->phy.ops.read_reg(hw, 0xC00C, IXGBE_TWINAX_DEV, &adapt_comp_reg); if (link_up_wait_to_complete) { - for (i = 0; i < IXGBE_LINK_UP_TIME; i++) { + for (i = 0; i < hw->mac.max_link_up_time; i++) { if ((link_reg & 1) && ((adapt_comp_reg & 1) == 0)) { *link_up = TRUE; @@ -695,7 +695,7 @@ int32_t ixgbe_check_mac_link_82598(struct ixgbe_hw *hw, links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS); if (link_up_wait_to_complete) { - for (i = 0; i < IXGBE_LINK_UP_TIME; i++) { + for (i = 0; i < hw->mac.max_link_up_time; i++) { if (links_reg & IXGBE_LINKS_UP) { *link_up = TRUE; break; diff --git a/sys/dev/pci/ixgbe_82599.c b/sys/dev/pci/ixgbe_82599.c index 12a12d59bd1..26e72fbf23b 100644 --- a/sys/dev/pci/ixgbe_82599.c +++ b/sys/dev/pci/ixgbe_82599.c @@ -1,8 +1,8 @@ -/* $OpenBSD: ixgbe_82599.c,v 1.14 2016/11/17 12:21:27 mikeb Exp $ */ +/* $OpenBSD: ixgbe_82599.c,v 1.15 2016/11/17 19:26:57 mikeb Exp $ */ /****************************************************************************** - 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 @@ -32,7 +32,7 @@ POSSIBILITY OF SUCH DAMAGE. ******************************************************************************/ -/* FreeBSD: src/sys/dev/ixgbe/ixgbe_82599.c 251964 Jun 18 21:28:19 2013 UTC */ +/*$FreeBSD: head/sys/dev/ixgbe/ixgbe_82599.c 292674 2015-12-23 22:45:17Z sbruno $*/ #include <dev/pci/ixgbe.h> #include <dev/pci/ixgbe_type.h> @@ -51,23 +51,16 @@ enum ixgbe_media_type ixgbe_get_media_type_82599(struct ixgbe_hw *hw); void ixgbe_disable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw); void ixgbe_enable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw); void ixgbe_flap_tx_laser_multispeed_fiber(struct ixgbe_hw *hw); -void ixgbe_set_fiber_fixed_speed(struct ixgbe_hw *hw, - ixgbe_link_speed speed); -int32_t ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw, - ixgbe_link_speed speed, - bool autoneg_wait_to_complete); +void ixgbe_set_hard_rate_select_speed(struct ixgbe_hw *hw, + ixgbe_link_speed speed); int32_t ixgbe_setup_mac_link_smartspeed(struct ixgbe_hw *hw, - ixgbe_link_speed speed, - bool autoneg_wait_to_complete); + ixgbe_link_speed speed, + bool autoneg_wait_to_complete); int32_t ixgbe_start_mac_link_82599(struct ixgbe_hw *hw, bool autoneg_wait_to_complete); -void ixgbe_stop_mac_link_on_d3_82599(struct ixgbe_hw *hw); int32_t ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw, - ixgbe_link_speed speed, - bool autoneg_wait_to_complete); -int32_t ixgbe_setup_copper_link_82599(struct ixgbe_hw *hw, - ixgbe_link_speed speed, - bool autoneg_wait_to_complete); + ixgbe_link_speed speed, + bool autoneg_wait_to_complete); int32_t ixgbe_setup_sfp_modules_82599(struct ixgbe_hw *hw); void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw); int32_t ixgbe_reset_hw_82599(struct ixgbe_hw *hw); @@ -80,32 +73,22 @@ int32_t ixgbe_identify_phy_82599(struct ixgbe_hw *hw); int32_t ixgbe_init_phy_ops_82599(struct ixgbe_hw *hw); uint32_t ixgbe_get_supported_physical_layer_82599(struct ixgbe_hw *hw); int32_t ixgbe_enable_rx_dma_82599(struct ixgbe_hw *hw, uint32_t regval); + +void ixgbe_stop_mac_link_on_d3_82599(struct ixgbe_hw *hw); + +int32_t ixgbe_setup_copper_link_82599(struct ixgbe_hw *hw, + ixgbe_link_speed speed, + bool autoneg_wait_to_complete); + int32_t ixgbe_verify_fw_version_82599(struct ixgbe_hw *hw); bool ixgbe_verify_lesm_fw_enabled_82599(struct ixgbe_hw *hw); +int32_t ixgbe_reset_pipeline_82599(struct ixgbe_hw *hw); int32_t ixgbe_read_eeprom_82599(struct ixgbe_hw *hw, uint16_t offset, uint16_t *data); -int32_t ixgbe_reset_pipeline_82599(struct ixgbe_hw *hw); -int32_t ixgbe_blink_led_start_82599(struct ixgbe_hw *hw, uint32_t index); -int32_t ixgbe_blink_led_stop_82599(struct ixgbe_hw *hw, uint32_t index); - -static bool ixgbe_mng_enabled(struct ixgbe_hw *hw) -{ - uint32_t fwsm, manc, factps; - - fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM); - if ((fwsm & IXGBE_FWSM_MODE_MASK) != IXGBE_FWSM_FW_MODE_PT) - return FALSE; - - manc = IXGBE_READ_REG(hw, IXGBE_MANC); - if (!(manc & IXGBE_MANC_RCV_TCO_EN)) - return FALSE; - - factps = IXGBE_READ_REG(hw, IXGBE_FACTPS); - if (factps & IXGBE_FACTPS_MNGCG) - return FALSE; - - return TRUE; -} +int32_t ixgbe_read_i2c_byte_82599(struct ixgbe_hw *hw, uint8_t byte_offset, + uint8_t dev_addr, uint8_t *data); +int32_t ixgbe_write_i2c_byte_82599(struct ixgbe_hw *hw, uint8_t byte_offset, + uint8_t dev_addr, uint8_t data); void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw) { @@ -118,7 +101,7 @@ void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw) * and MNG not enabled */ if ((mac->ops.get_media_type(hw) == ixgbe_media_type_fiber) && - !hw->mng_fw_enabled) { + !ixgbe_mng_enabled(hw)) { mac->ops.disable_tx_laser = ixgbe_disable_tx_laser_multispeed_fiber; mac->ops.enable_tx_laser = @@ -134,6 +117,12 @@ void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw) if (hw->phy.multispeed_fiber) { /* Set up dual speed SFP+ support */ mac->ops.setup_link = ixgbe_setup_mac_link_multispeed_fiber; + mac->ops.setup_mac_link = ixgbe_setup_mac_link_82599; + mac->ops.set_rate_select_speed = + ixgbe_set_hard_rate_select_speed; + if (ixgbe_get_media_type(hw) == ixgbe_media_type_fiber_fixed) + mac->ops.set_rate_select_speed = + ixgbe_set_soft_rate_select_speed; } else { if ((ixgbe_get_media_type(hw) == ixgbe_media_type_backplane) && (hw->phy.smart_speed == ixgbe_smart_speed_auto || @@ -160,9 +149,27 @@ int32_t ixgbe_init_phy_ops_82599(struct ixgbe_hw *hw) struct ixgbe_mac_info *mac = &hw->mac; struct ixgbe_phy_info *phy = &hw->phy; int32_t ret_val = IXGBE_SUCCESS; + uint32_t esdp; DEBUGFUNC("ixgbe_init_phy_ops_82599"); + if (hw->device_id == IXGBE_DEV_ID_82599_QSFP_SF_QP) { + /* Store flag indicating I2C bus access control unit. */ + hw->phy.qsfp_shared_i2c_bus = TRUE; + + /* Initialize access to QSFP+ I2C bus */ + esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); + esdp |= IXGBE_ESDP_SDP0_DIR; + esdp &= ~IXGBE_ESDP_SDP1_DIR; + esdp &= ~IXGBE_ESDP_SDP0; + esdp &= ~IXGBE_ESDP_SDP0_NATIVE; + esdp &= ~IXGBE_ESDP_SDP1_NATIVE; + IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); + IXGBE_WRITE_FLUSH(hw); + + phy->ops.read_i2c_byte = ixgbe_read_i2c_byte_82599; + phy->ops.write_i2c_byte = ixgbe_write_i2c_byte_82599; + } /* Identify the PHY or SFP module */ ret_val = phy->ops.identify(hw); if (ret_val == IXGBE_ERR_SFP_NOT_SUPPORTED) @@ -300,7 +307,7 @@ int32_t ixgbe_init_ops_82599(struct ixgbe_hw *hw) DEBUGFUNC("ixgbe_init_ops_82599"); - ixgbe_init_phy_ops_generic(hw); + ret_val = ixgbe_init_phy_ops_generic(hw); ret_val = ixgbe_init_ops_generic(hw); /* PHY */ @@ -331,20 +338,20 @@ int32_t ixgbe_init_ops_82599(struct ixgbe_hw *hw) mac->ops.setup_sfp = ixgbe_setup_sfp_modules_82599; mac->ops.verify_lesm_fw_enabled = ixgbe_verify_lesm_fw_enabled_82599; - mac->ops.reset_pipeline = ixgbe_reset_pipeline_82599; mac->ops.stop_mac_link_on_d3 = ixgbe_stop_mac_link_on_d3_82599; /* Link */ mac->ops.get_link_capabilities = ixgbe_get_link_capabilities_82599; mac->ops.check_link = ixgbe_check_mac_link_generic; + mac->ops.stop_mac_link_on_d3 = ixgbe_stop_mac_link_on_d3_82599; ixgbe_init_mac_link_ops_82599(hw); mac->mcft_size = IXGBE_82599_MC_TBL_SIZE; mac->vft_size = IXGBE_82599_VFT_TBL_SIZE; mac->num_rar_entries = IXGBE_82599_RAR_ENTRIES; mac->rx_pb_size = IXGBE_82599_RX_PB_SIZE; - mac->max_tx_queues = IXGBE_82599_MAX_TX_QUEUES; mac->max_rx_queues = IXGBE_82599_MAX_RX_QUEUES; + mac->max_tx_queues = IXGBE_82599_MAX_TX_QUEUES; mac->max_msix_vectors = 0 /*ixgbe_get_pcie_msix_count_generic(hw)*/; hw->mbx.ops.init_params = ixgbe_init_mbx_params_pf; @@ -352,9 +359,6 @@ int32_t ixgbe_init_ops_82599(struct ixgbe_hw *hw) /* EEPROM */ eeprom->ops.read = ixgbe_read_eeprom_82599; - /* Cache if MNG FW is up */ - hw->mng_fw_enabled = ixgbe_mng_enabled(hw); - return ret_val; } @@ -455,7 +459,14 @@ int32_t ixgbe_get_link_capabilities_82599(struct ixgbe_hw *hw, if (hw->phy.multispeed_fiber) { *speed |= IXGBE_LINK_SPEED_10GB_FULL | IXGBE_LINK_SPEED_1GB_FULL; - *autoneg = TRUE; + + /* QSFP must not enable full auto-negotiation + * Limited autoneg is enabled at 1G + */ + if (hw->phy.media_type == ixgbe_media_type_fiber_qsfp) + *autoneg = FALSE; + else + *autoneg = TRUE; } out: @@ -508,6 +519,9 @@ enum ixgbe_media_type ixgbe_get_media_type_82599(struct ixgbe_hw *hw) case IXGBE_DEV_ID_82599_T3_LOM: media_type = ixgbe_media_type_copper; break; + case IXGBE_DEV_ID_82599_QSFP_SF_QP: + media_type = ixgbe_media_type_fiber_qsfp; + break; case IXGBE_DEV_ID_82599_BYPASS: media_type = ixgbe_media_type_fiber_fixed; hw->phy.multispeed_fiber = TRUE; @@ -535,7 +549,8 @@ void ixgbe_stop_mac_link_on_d3_82599(struct ixgbe_hw *hw) DEBUGFUNC("ixgbe_stop_mac_link_on_d3_82599"); ixgbe_read_eeprom_82599(hw, IXGBE_EEPROM_CTRL_2, &ee_ctrl_2); - if (!hw->mng_fw_enabled && ee_ctrl_2 & IXGBE_EEPROM_CCD_BIT) { + if (!ixgbe_mng_present(hw) && + (ee_ctrl_2 & IXGBE_EEPROM_CCD_BIT)) { autoc2_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC2); autoc2_reg |= IXGBE_AUTOC2_LINK_DISABLE_ON_D3_MASK; IXGBE_WRITE_REG(hw, IXGBE_AUTOC2, autoc2_reg); @@ -622,6 +637,10 @@ void ixgbe_disable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw) { uint32_t esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP); + /* Blocked by MNG FW so bail */ + if (ixgbe_check_reset_blocked(hw)) + return; + /* Disable Tx laser; allow 100us to go dark per spec */ esdp_reg |= IXGBE_ESDP_SDP3; IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg); @@ -664,6 +683,10 @@ void ixgbe_flap_tx_laser_multispeed_fiber(struct ixgbe_hw *hw) { DEBUGFUNC("ixgbe_flap_tx_laser_multispeed_fiber"); + /* Blocked by MNG FW so bail */ + if (ixgbe_check_reset_blocked(hw)) + return; + if (hw->mac.autotry_restart) { ixgbe_disable_tx_laser_multispeed_fiber(hw); ixgbe_enable_tx_laser_multispeed_fiber(hw); @@ -672,229 +695,32 @@ void ixgbe_flap_tx_laser_multispeed_fiber(struct ixgbe_hw *hw) } /** - * ixgbe_set_fiber_fixed_speed - Set module link speed for fixed fiber + * ixgbe_set_hard_rate_select_speed - Set module link speed * @hw: pointer to hardware structure * @speed: link speed to set * - * We set the module speed differently for fixed fiber. For other - * multi-speed devices we don't have an error value so here if we - * detect an error we just log it and exit. + * Set module link speed via RS0/RS1 rate select pins. */ -void ixgbe_set_fiber_fixed_speed(struct ixgbe_hw *hw, - ixgbe_link_speed speed) +void ixgbe_set_hard_rate_select_speed(struct ixgbe_hw *hw, + ixgbe_link_speed speed) { - int32_t status; - uint8_t rs, eeprom_data; + uint32_t esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP); switch (speed) { case IXGBE_LINK_SPEED_10GB_FULL: - /* one bit mask same as setting on */ - rs = IXGBE_SFF_SOFT_RS_SELECT_10G; + esdp_reg |= (IXGBE_ESDP_SDP5_DIR | IXGBE_ESDP_SDP5); break; case IXGBE_LINK_SPEED_1GB_FULL: - rs = IXGBE_SFF_SOFT_RS_SELECT_1G; + esdp_reg &= ~IXGBE_ESDP_SDP5; + esdp_reg |= IXGBE_ESDP_SDP5_DIR; break; default: DEBUGOUT("Invalid fixed module speed\n"); return; } - /* Set RS0 */ - status = hw->phy.ops.read_i2c_byte(hw, IXGBE_SFF_SFF_8472_OSCB, - IXGBE_I2C_EEPROM_DEV_ADDR2, - &eeprom_data); - if (status) { - DEBUGOUT("Failed to read Rx Rate Select RS0\n"); - goto out; - } - - eeprom_data = (eeprom_data & ~IXGBE_SFF_SOFT_RS_SELECT_MASK) & rs; - - status = hw->phy.ops.write_i2c_byte(hw, IXGBE_SFF_SFF_8472_OSCB, - IXGBE_I2C_EEPROM_DEV_ADDR2, - eeprom_data); - if (status) { - DEBUGOUT("Failed to write Rx Rate Select RS0\n"); - goto out; - } - - /* Set RS1 */ - status = hw->phy.ops.read_i2c_byte(hw, IXGBE_SFF_SFF_8472_ESCB, - IXGBE_I2C_EEPROM_DEV_ADDR2, - &eeprom_data); - if (status) { - DEBUGOUT("Failed to read Rx Rate Select RS1\n"); - goto out; - } - - eeprom_data = (eeprom_data & ~IXGBE_SFF_SOFT_RS_SELECT_MASK) & rs; - - status = hw->phy.ops.write_i2c_byte(hw, IXGBE_SFF_SFF_8472_ESCB, - IXGBE_I2C_EEPROM_DEV_ADDR2, - eeprom_data); - if (status) { - DEBUGOUT("Failed to write Rx Rate Select RS1\n"); - goto out; - } -out: - return; -} - -/** - * ixgbe_setup_mac_link_multispeed_fiber - Set MAC link speed - * @hw: pointer to hardware structure - * @speed: new link speed - * @autoneg_wait_to_complete: TRUE when waiting for completion is needed - * - * Set the link speed in the AUTOC register and restarts link. - **/ -int32_t ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw, - ixgbe_link_speed speed, - bool autoneg_wait_to_complete) -{ - int32_t status = IXGBE_SUCCESS; - ixgbe_link_speed link_speed = IXGBE_LINK_SPEED_UNKNOWN; - ixgbe_link_speed highest_link_speed = IXGBE_LINK_SPEED_UNKNOWN; - uint32_t speedcnt = 0; - uint32_t esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP); - uint32_t i = 0; - bool autoneg, link_up = FALSE; - - DEBUGFUNC("ixgbe_setup_mac_link_multispeed_fiber"); - - /* Mask off requested but non-supported speeds */ - status = ixgbe_get_link_capabilities_82599(hw, &link_speed, &autoneg); - if (status != IXGBE_SUCCESS) - return status; - - speed &= link_speed; - - /* - * Try each speed one by one, highest priority first. We do this in - * software because 10gb fiber doesn't support speed autonegotiation. - */ - if (speed & IXGBE_LINK_SPEED_10GB_FULL) { - speedcnt++; - highest_link_speed = IXGBE_LINK_SPEED_10GB_FULL; - - /* If we already have link at this speed, just jump out */ - status = ixgbe_check_link(hw, &link_speed, &link_up, FALSE); - if (status != IXGBE_SUCCESS) - return status; - - if ((link_speed == IXGBE_LINK_SPEED_10GB_FULL) && link_up) - goto out; - - /* Set the module link speed */ - if (hw->phy.media_type == ixgbe_media_type_fiber_fixed) { - ixgbe_set_fiber_fixed_speed(hw, - IXGBE_LINK_SPEED_10GB_FULL); - } else { - esdp_reg |= (IXGBE_ESDP_SDP5_DIR | IXGBE_ESDP_SDP5); - IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg); - IXGBE_WRITE_FLUSH(hw); - } - - /* Allow module to change analog characteristics (1G->10G) */ - msec_delay(40); - - status = ixgbe_setup_mac_link_82599(hw, - IXGBE_LINK_SPEED_10GB_FULL, - autoneg_wait_to_complete); - if (status != IXGBE_SUCCESS) - return status; - - /* Flap the tx laser if it has not already been done */ - ixgbe_flap_tx_laser(hw); - - /* - * Wait for the controller to acquire link. Per IEEE 802.3ap, - * Section 73.10.2, we may have to wait up to 500ms if KR is - * attempted. 82599 uses the same timing for 10g SFI. - */ - for (i = 0; i < 5; i++) { - /* Wait for the link partner to also set speed */ - msec_delay(100); - - /* If we have link, just jump out */ - status = ixgbe_check_link(hw, &link_speed, - &link_up, FALSE); - if (status != IXGBE_SUCCESS) - return status; - - if (link_up) - goto out; - } - } - - if (speed & IXGBE_LINK_SPEED_1GB_FULL) { - speedcnt++; - if (highest_link_speed == IXGBE_LINK_SPEED_UNKNOWN) - highest_link_speed = IXGBE_LINK_SPEED_1GB_FULL; - - /* If we already have link at this speed, just jump out */ - status = ixgbe_check_link(hw, &link_speed, &link_up, FALSE); - if (status != IXGBE_SUCCESS) - return status; - - if ((link_speed == IXGBE_LINK_SPEED_1GB_FULL) && link_up) - goto out; - - /* Set the module link speed */ - if (hw->phy.media_type == ixgbe_media_type_fiber_fixed) { - ixgbe_set_fiber_fixed_speed(hw, - IXGBE_LINK_SPEED_1GB_FULL); - } else { - esdp_reg &= ~IXGBE_ESDP_SDP5; - esdp_reg |= IXGBE_ESDP_SDP5_DIR; - IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg); - IXGBE_WRITE_FLUSH(hw); - } - - /* Allow module to change analog characteristics (10G->1G) */ - msec_delay(40); - - status = ixgbe_setup_mac_link_82599(hw, - IXGBE_LINK_SPEED_1GB_FULL, - autoneg_wait_to_complete); - if (status != IXGBE_SUCCESS) - return status; - - /* Flap the tx laser if it has not already been done */ - ixgbe_flap_tx_laser(hw); - - /* Wait for the link partner to also set speed */ - msec_delay(100); - - /* If we have link, just jump out */ - status = ixgbe_check_link(hw, &link_speed, &link_up, FALSE); - if (status != IXGBE_SUCCESS) - return status; - - if (link_up) - goto out; - } - - /* - * We didn't get link. Configure back to the highest speed we tried, - * (if there was more than one). We call ourselves back with just the - * single highest speed that the user requested. - */ - if (speedcnt > 1) - status = ixgbe_setup_mac_link_multispeed_fiber(hw, - highest_link_speed, autoneg_wait_to_complete); - -out: - /* Set autoneg_advertised value based on input link speed */ - hw->phy.autoneg_advertised = 0; - - if (speed & IXGBE_LINK_SPEED_10GB_FULL) - hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_10GB_FULL; - - if (speed & IXGBE_LINK_SPEED_1GB_FULL) - hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL; - - return status; + IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg); + IXGBE_WRITE_FLUSH(hw); } /** @@ -1035,7 +861,8 @@ int32_t ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw, DEBUGFUNC("ixgbe_setup_mac_link_82599"); /* Check to see if speed passed in is supported. */ - status = ixgbe_get_link_capabilities_82599(hw, &link_capabilities, &autoneg); + status = ixgbe_get_link_capabilities_82599(hw, &link_capabilities, + &autoneg); if (status) goto out; @@ -1086,7 +913,7 @@ int32_t ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw, if ((speed == IXGBE_LINK_SPEED_1GB_FULL) && (pma_pmd_1g == IXGBE_AUTOC_1G_SFI)) { autoc &= ~IXGBE_AUTOC_LMS_MASK; - if (autoneg) + if (autoneg || hw->phy.type == ixgbe_phy_qsfp_intel) autoc |= IXGBE_AUTOC_LMS_1G_AN; else autoc |= IXGBE_AUTOC_LMS_1G_LINK_NO_AN; @@ -1298,7 +1125,7 @@ mac_reset_top: * Likewise if we support WoL we don't want change the * LMS state. */ - if (hw->phy.multispeed_fiber && hw->mng_fw_enabled) + if (hw->phy.multispeed_fiber && ixgbe_mng_enabled(hw)) hw->mac.orig_autoc = (hw->mac.orig_autoc & ~IXGBE_AUTOC_LMS_MASK) | curr_lms; @@ -1442,7 +1269,7 @@ out: **/ int32_t ixgbe_identify_phy_82599(struct ixgbe_hw *hw) { - int32_t status = IXGBE_ERR_PHY_ADDR_INVALID; + int32_t status; DEBUGFUNC("ixgbe_identify_phy_82599"); @@ -1451,7 +1278,7 @@ int32_t ixgbe_identify_phy_82599(struct ixgbe_hw *hw) if (status != IXGBE_SUCCESS) { /* 82599 10GBASE-T requires an external PHY */ if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_copper) - goto out; + return status; else status = ixgbe_identify_module_generic(hw); } @@ -1459,14 +1286,13 @@ int32_t ixgbe_identify_phy_82599(struct ixgbe_hw *hw) /* Set PHY type none if no PHY detected */ if (hw->phy.type == ixgbe_phy_unknown) { hw->phy.type = ixgbe_phy_none; - status = IXGBE_SUCCESS; + return IXGBE_SUCCESS; } /* Return error if SFP module has been detected but is not supported */ if (hw->phy.type == ixgbe_phy_sfp_unsupported) - status = IXGBE_ERR_SFP_NOT_SUPPORTED; + return IXGBE_ERR_SFP_NOT_SUPPORTED; -out: return status; } @@ -1485,8 +1311,6 @@ uint32_t ixgbe_get_supported_physical_layer_82599(struct ixgbe_hw *hw) uint32_t pma_pmd_10g_parallel = autoc & IXGBE_AUTOC_10G_PMA_PMD_MASK; uint32_t pma_pmd_1g = autoc & IXGBE_AUTOC_1G_PMA_PMD_MASK; uint16_t ext_ability = 0; - uint8_t comp_codes_10g = 0; - uint8_t comp_codes_1g = 0; DEBUGFUNC("ixgbe_get_support_physical_layer_82599"); @@ -1554,47 +1378,7 @@ sfp_check: /* SFP check must be done last since DA modules are sometimes used to * test KR mode - we need to id KR mode correctly before SFP module. * Call identify_sfp because the pluggable module may have changed */ - hw->phy.ops.identify_sfp(hw); - if (hw->phy.sfp_type == ixgbe_sfp_type_not_present) - goto out; - - switch (hw->phy.type) { - case ixgbe_phy_sfp_passive_tyco: - case ixgbe_phy_sfp_passive_unknown: - physical_layer = IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU; - break; - case ixgbe_phy_sfp_ftl_active: - case ixgbe_phy_sfp_active_unknown: - physical_layer = IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA; - break; - case ixgbe_phy_sfp_avago: - case ixgbe_phy_sfp_ftl: - case ixgbe_phy_sfp_intel: - case ixgbe_phy_sfp_unknown: - hw->phy.ops.read_i2c_eeprom(hw, - IXGBE_SFF_1GBE_COMP_CODES, &comp_codes_1g); - hw->phy.ops.read_i2c_eeprom(hw, - IXGBE_SFF_10GBE_COMP_CODES, &comp_codes_10g); - if (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE) - physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_SR; - else if (comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE) - physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_LR; - else if (comp_codes_10g & - (IXGBE_SFF_DA_PASSIVE_CABLE | IXGBE_SFF_DA_BAD_HP_CABLE)) - physical_layer = IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU; - else if (comp_codes_10g & IXGBE_SFF_DA_ACTIVE_CABLE) - physical_layer = IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA; - else if (comp_codes_1g & IXGBE_SFF_1GBASET_CAPABLE) - physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_T; - else if (comp_codes_1g & IXGBE_SFF_1GBASESX_CAPABLE) - physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_SX; - else if (comp_codes_1g & IXGBE_SFF_1GBASELX_CAPABLE) - physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_LX; - break; - default: - break; - } - + physical_layer = ixgbe_get_supported_phy_sfp_layer_generic(hw); out: return physical_layer; } @@ -1620,7 +1404,10 @@ int32_t ixgbe_enable_rx_dma_82599(struct ixgbe_hw *hw, uint32_t regval) hw->mac.ops.disable_sec_rx_path(hw); - IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, regval); + if (regval & IXGBE_RXCTRL_RXEN) + ixgbe_enable_rx(hw); + else + ixgbe_disable_rx(hw); hw->mac.ops.enable_sec_rx_path(hw); @@ -1815,3 +1602,117 @@ reset_pipeline_out: return ret_val; } + +/** + * ixgbe_read_i2c_byte_82599 - Reads 8 bit word over I2C + * @hw: pointer to hardware structure + * @byte_offset: byte offset to read + * @data: value read + * + * Performs byte read operation to SFP module's EEPROM over I2C interface at + * a specified device address. + **/ +int32_t ixgbe_read_i2c_byte_82599(struct ixgbe_hw *hw, uint8_t byte_offset, + uint8_t dev_addr, uint8_t *data) +{ + uint32_t esdp; + int32_t status; + int32_t timeout = 200; + + DEBUGFUNC("ixgbe_read_i2c_byte_82599"); + + if (hw->phy.qsfp_shared_i2c_bus == TRUE) { + /* Acquire I2C bus ownership. */ + esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); + esdp |= IXGBE_ESDP_SDP0; + IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); + IXGBE_WRITE_FLUSH(hw); + + while (timeout) { + esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); + if (esdp & IXGBE_ESDP_SDP1) + break; + + msec_delay(5); + timeout--; + } + + if (!timeout) { + DEBUGOUT("Driver can't access resource," + " acquiring I2C bus timeout.\n"); + status = IXGBE_ERR_I2C; + goto release_i2c_access; + } + } + + status = ixgbe_read_i2c_byte_generic(hw, byte_offset, dev_addr, data); + +release_i2c_access: + + if (hw->phy.qsfp_shared_i2c_bus == TRUE) { + /* Release I2C bus ownership. */ + esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); + esdp &= ~IXGBE_ESDP_SDP0; + IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); + IXGBE_WRITE_FLUSH(hw); + } + + return status; +} + +/** + * ixgbe_write_i2c_byte_82599 - Writes 8 bit word over I2C + * @hw: pointer to hardware structure + * @byte_offset: byte offset to write + * @data: value to write + * + * Performs byte write operation to SFP module's EEPROM over I2C interface at + * a specified device address. + **/ +int32_t ixgbe_write_i2c_byte_82599(struct ixgbe_hw *hw, uint8_t byte_offset, + uint8_t dev_addr, uint8_t data) +{ + uint32_t esdp; + int32_t status; + int32_t timeout = 200; + + DEBUGFUNC("ixgbe_write_i2c_byte_82599"); + + if (hw->phy.qsfp_shared_i2c_bus == TRUE) { + /* Acquire I2C bus ownership. */ + esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); + esdp |= IXGBE_ESDP_SDP0; + IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); + IXGBE_WRITE_FLUSH(hw); + + while (timeout) { + esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); + if (esdp & IXGBE_ESDP_SDP1) + break; + + msec_delay(5); + timeout--; + } + + if (!timeout) { + DEBUGOUT("Driver can't access resource," + " acquiring I2C bus timeout.\n"); + status = IXGBE_ERR_I2C; + goto release_i2c_access; + } + } + + status = ixgbe_write_i2c_byte_generic(hw, byte_offset, dev_addr, data); + +release_i2c_access: + + if (hw->phy.qsfp_shared_i2c_bus == TRUE) { + /* Release I2C bus ownership. */ + esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); + esdp &= ~IXGBE_ESDP_SDP0; + IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); + IXGBE_WRITE_FLUSH(hw); + } + + return status; +} diff --git a/sys/dev/pci/ixgbe_phy.c b/sys/dev/pci/ixgbe_phy.c index 0a6834d0c7c..0403ced1354 100644 --- a/sys/dev/pci/ixgbe_phy.c +++ b/sys/dev/pci/ixgbe_phy.c @@ -1,8 +1,8 @@ -/* $OpenBSD: ixgbe_phy.c,v 1.14 2016/11/17 12:21:27 mikeb Exp $ */ +/* $OpenBSD: ixgbe_phy.c,v 1.15 2016/11/17 19:26:57 mikeb Exp $ */ /****************************************************************************** - 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 @@ -138,6 +138,35 @@ int32_t ixgbe_identify_phy_generic(struct ixgbe_hw *hw) } /** + * ixgbe_check_reset_blocked - check status of MNG FW veto bit + * @hw: pointer to the hardware structure + * + * This function checks the MMNGC.MNG_VETO bit to see if there are + * any constraints on link from manageability. For MAC's that don't + * have this bit just return faluse since the link can not be blocked + * via this method. + **/ +int32_t ixgbe_check_reset_blocked(struct ixgbe_hw *hw) +{ + uint32_t mmngc; + + DEBUGFUNC("ixgbe_check_reset_blocked"); + + /* If we don't have this bit, it can't be blocking */ + if (hw->mac.type == ixgbe_mac_82598EB) + return FALSE; + + mmngc = IXGBE_READ_REG(hw, IXGBE_MMNGC); + if (mmngc & IXGBE_MMNGC_MNG_VETO) { + ERROR_REPORT1(IXGBE_ERROR_SOFTWARE, + "MNG_VETO bit detected.\n"); + return TRUE; + } + + return FALSE; +} + +/** * ixgbe_validate_phy_addr - Determines phy address is valid * @hw: pointer to hardware structure * @@ -182,7 +211,8 @@ int32_t ixgbe_get_phy_id(struct ixgbe_hw *hw) IXGBE_MDIO_PMA_PMD_DEV_TYPE, &phy_id_low); hw->phy.id |= (uint32_t)(phy_id_low & IXGBE_PHY_REVISION_MASK); - hw->phy.revision = (uint32_t)(phy_id_low & ~IXGBE_PHY_REVISION_MASK); + hw->phy.revision = + (uint32_t)(phy_id_low & ~IXGBE_PHY_REVISION_MASK); } return status; } @@ -202,6 +232,9 @@ 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 X550_PHY_ID1: + case X550_PHY_ID2: + case X550_PHY_ID3: case X540_PHY_ID: phy_type = ixgbe_phy_aq; break; @@ -211,6 +244,9 @@ enum ixgbe_phy_type ixgbe_get_phy_type_from_id(uint32_t phy_id) case ATH_PHY_ID: phy_type = ixgbe_phy_nl; break; + case X557_PHY_ID: + phy_type = ixgbe_phy_x550em_ext_t; + break; default: phy_type = ixgbe_phy_unknown; break; @@ -243,6 +279,10 @@ int32_t ixgbe_reset_phy_generic(struct ixgbe_hw *hw) (IXGBE_ERR_OVERTEMP == hw->phy.ops.check_overtemp(hw))) goto out; + /* Blocked by MNG FW so bail */ + if (ixgbe_check_reset_blocked(hw)) + goto out; + /* * Perform soft PHY reset to the PHY_XS. * This will cause a soft reset to the PHY @@ -526,6 +566,44 @@ int32_t ixgbe_setup_phy_link_generic(struct ixgbe_hw *hw) autoneg_reg); } + if (hw->mac.type == ixgbe_mac_X550) { + if (speed & IXGBE_LINK_SPEED_5GB_FULL) { + /* Set or unset auto-negotiation 5G advertisement */ + hw->phy.ops.read_reg(hw, + IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG, + IXGBE_MDIO_AUTO_NEG_DEV_TYPE, + &autoneg_reg); + + autoneg_reg &= ~IXGBE_MII_5GBASE_T_ADVERTISE; + if (hw->phy.autoneg_advertised & + IXGBE_LINK_SPEED_5GB_FULL) + autoneg_reg |= IXGBE_MII_5GBASE_T_ADVERTISE; + + hw->phy.ops.write_reg(hw, + IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG, + IXGBE_MDIO_AUTO_NEG_DEV_TYPE, + autoneg_reg); + } + + if (speed & IXGBE_LINK_SPEED_2_5GB_FULL) { + /* Set or unset auto-negotiation 2.5G advertisement */ + hw->phy.ops.read_reg(hw, + IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG, + IXGBE_MDIO_AUTO_NEG_DEV_TYPE, + &autoneg_reg); + + autoneg_reg &= ~IXGBE_MII_2_5GBASE_T_ADVERTISE; + if (hw->phy.autoneg_advertised & + IXGBE_LINK_SPEED_2_5GB_FULL) + autoneg_reg |= IXGBE_MII_2_5GBASE_T_ADVERTISE; + + hw->phy.ops.write_reg(hw, + IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG, + IXGBE_MDIO_AUTO_NEG_DEV_TYPE, + autoneg_reg); + } + } + if (speed & IXGBE_LINK_SPEED_1GB_FULL) { /* Set or unset auto-negotiation 1G advertisement */ hw->phy.ops.read_reg(hw, @@ -610,6 +688,12 @@ int32_t ixgbe_setup_phy_link_speed_generic(struct ixgbe_hw *hw, if (speed & IXGBE_LINK_SPEED_10GB_FULL) hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_10GB_FULL; + if (speed & IXGBE_LINK_SPEED_5GB_FULL) + hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_5GB_FULL; + + if (speed & IXGBE_LINK_SPEED_2_5GB_FULL) + hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_2_5GB_FULL; + if (speed & IXGBE_LINK_SPEED_1GB_FULL) hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL; @@ -623,6 +707,46 @@ int32_t ixgbe_setup_phy_link_speed_generic(struct ixgbe_hw *hw, } /** + * ixgbe_get_copper_speeds_supported - Get copper link speeds from phy + * @hw: pointer to hardware structure + * + * Determines the supported link capabilities by reading the PHY auto + * negotiation register. + **/ +int32_t ixgbe_get_copper_speeds_supported(struct ixgbe_hw *hw) +{ + int32_t status; + uint16_t speed_ability; + + status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_SPEED_ABILITY, + IXGBE_MDIO_PMA_PMD_DEV_TYPE, + &speed_ability); + if (status) + return status; + + if (speed_ability & IXGBE_MDIO_PHY_SPEED_10G) + hw->phy.speeds_supported |= IXGBE_LINK_SPEED_10GB_FULL; + if (speed_ability & IXGBE_MDIO_PHY_SPEED_1G) + hw->phy.speeds_supported |= IXGBE_LINK_SPEED_1GB_FULL; + if (speed_ability & IXGBE_MDIO_PHY_SPEED_100M) + hw->phy.speeds_supported |= IXGBE_LINK_SPEED_100_FULL; + + switch (hw->mac.type) { + case ixgbe_mac_X550: + hw->phy.speeds_supported |= IXGBE_LINK_SPEED_2_5GB_FULL; + hw->phy.speeds_supported |= IXGBE_LINK_SPEED_5GB_FULL; + break; + case ixgbe_mac_X550EM_x: + hw->phy.speeds_supported &= ~IXGBE_LINK_SPEED_100_FULL; + break; + default: + break; + } + + return status; +} + +/** * ixgbe_get_copper_link_capabilities_generic - Determines link capabilities * @hw: pointer to hardware structure * @speed: pointer to link speed @@ -809,7 +933,7 @@ int32_t ixgbe_setup_phy_link_tnx(struct ixgbe_hw *hw) int32_t ixgbe_get_phy_firmware_version_tnx(struct ixgbe_hw *hw, uint16_t *firmware_version) { - int32_t status = IXGBE_SUCCESS; + int32_t status; DEBUGFUNC("ixgbe_get_phy_firmware_version_tnx"); @@ -828,7 +952,7 @@ int32_t ixgbe_get_phy_firmware_version_tnx(struct ixgbe_hw *hw, int32_t ixgbe_get_phy_firmware_version_generic(struct ixgbe_hw *hw, uint16_t *firmware_version) { - int32_t status = IXGBE_SUCCESS; + int32_t status; DEBUGFUNC("ixgbe_get_phy_firmware_version_generic"); @@ -951,6 +1075,26 @@ err_eeprom: return IXGBE_ERR_PHY; } +bool +ixgbe_is_sfp(struct ixgbe_hw *hw) +{ + switch (hw->phy.type) { + case ixgbe_phy_sfp_avago: + case ixgbe_phy_sfp_ftl: + case ixgbe_phy_sfp_intel: + case ixgbe_phy_sfp_unknown: + case ixgbe_phy_sfp_passive_tyco: + case ixgbe_phy_sfp_passive_unknown: + case ixgbe_phy_qsfp_passive_unknown: + case ixgbe_phy_qsfp_active_unknown: + case ixgbe_phy_qsfp_intel: + case ixgbe_phy_qsfp_unknown: + return TRUE; + default: + return FALSE; + } +} + /** * ixgbe_identify_module_generic - Identifies module type * @hw: pointer to hardware structure @@ -968,6 +1112,9 @@ int32_t ixgbe_identify_module_generic(struct ixgbe_hw *hw) status = ixgbe_identify_sfp_module_generic(hw); break; + case ixgbe_media_type_fiber_qsfp: + status = ixgbe_identify_qsfp_module_generic(hw); + break; default: hw->phy.sfp_type = ixgbe_sfp_type_not_present; @@ -1183,21 +1330,18 @@ int32_t ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw) hw->phy.type = ixgbe_phy_sfp_intel; break; default: - if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE) - hw->phy.type = - ixgbe_phy_sfp_passive_unknown; - else if (cable_tech & IXGBE_SFF_DA_ACTIVE_CABLE) - hw->phy.type = - ixgbe_phy_sfp_active_unknown; - else - hw->phy.type = ixgbe_phy_sfp_unknown; + hw->phy.type = ixgbe_phy_sfp_unknown; break; } } /* Allow any DA cable vendor */ if (cable_tech & (IXGBE_SFF_DA_PASSIVE_CABLE | - IXGBE_SFF_DA_ACTIVE_CABLE)) { + IXGBE_SFF_DA_ACTIVE_CABLE)) { + if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE) + hw->phy.type = ixgbe_phy_sfp_passive_unknown; + else if (cable_tech & IXGBE_SFF_DA_ACTIVE_CABLE) + hw->phy.type = ixgbe_phy_sfp_active_unknown; status = IXGBE_SUCCESS; goto out; } @@ -1235,6 +1379,251 @@ err_read_i2c_eeprom: } /** + * ixgbe_get_supported_phy_sfp_layer_generic - Returns physical layer type + * @hw: pointer to hardware structure + * + * Determines physical layer capabilities of the current SFP. + */ +int32_t ixgbe_get_supported_phy_sfp_layer_generic(struct ixgbe_hw *hw) +{ + uint32_t physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN; + uint8_t comp_codes_10g = 0; + uint8_t comp_codes_1g = 0; + + DEBUGFUNC("ixgbe_get_supported_phy_sfp_layer_generic"); + + hw->phy.ops.identify_sfp(hw); + if (hw->phy.sfp_type == ixgbe_sfp_type_not_present) + return physical_layer; + + switch (hw->phy.type) { + case ixgbe_phy_sfp_passive_tyco: + case ixgbe_phy_sfp_passive_unknown: + case ixgbe_phy_qsfp_passive_unknown: + physical_layer = IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU; + break; + case ixgbe_phy_sfp_ftl_active: + case ixgbe_phy_sfp_active_unknown: + case ixgbe_phy_qsfp_active_unknown: + physical_layer = IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA; + break; + case ixgbe_phy_sfp_avago: + case ixgbe_phy_sfp_ftl: + case ixgbe_phy_sfp_intel: + case ixgbe_phy_sfp_unknown: + hw->phy.ops.read_i2c_eeprom(hw, + IXGBE_SFF_1GBE_COMP_CODES, &comp_codes_1g); + hw->phy.ops.read_i2c_eeprom(hw, + IXGBE_SFF_10GBE_COMP_CODES, &comp_codes_10g); + if (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE) + physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_SR; + else if (comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE) + physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_LR; + else if (comp_codes_10g & + (IXGBE_SFF_DA_PASSIVE_CABLE | IXGBE_SFF_DA_BAD_HP_CABLE)) + physical_layer = IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU; + else if (comp_codes_10g & IXGBE_SFF_DA_ACTIVE_CABLE) + physical_layer = IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA; + else if (comp_codes_1g & IXGBE_SFF_1GBASET_CAPABLE) + physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_T; + else if (comp_codes_1g & IXGBE_SFF_1GBASESX_CAPABLE) + physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_SX; + else if (comp_codes_1g & IXGBE_SFF_1GBASELX_CAPABLE) + physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_LX; + break; + case ixgbe_phy_qsfp_intel: + case ixgbe_phy_qsfp_unknown: + hw->phy.ops.read_i2c_eeprom(hw, + IXGBE_SFF_QSFP_10GBE_COMP, &comp_codes_10g); + if (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE) + physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_SR; + else if (comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE) + physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_LR; + break; + default: + break; + } + + return physical_layer; +} + +/** + * ixgbe_identify_qsfp_module_generic - Identifies QSFP modules + * @hw: pointer to hardware structure + * + * Searches for and identifies the QSFP module and assigns appropriate PHY type + **/ +int32_t ixgbe_identify_qsfp_module_generic(struct ixgbe_hw *hw) +{ + int32_t status = IXGBE_ERR_PHY_ADDR_INVALID; + uint32_t vendor_oui = 0; + enum ixgbe_sfp_type stored_sfp_type = hw->phy.sfp_type; + uint8_t identifier = 0; + uint8_t comp_codes_1g = 0; + uint8_t comp_codes_10g = 0; + uint8_t oui_bytes[3] = {0, 0, 0}; + uint8_t connector = 0; + uint8_t cable_length = 0; + uint8_t device_tech = 0; + bool active_cable = FALSE; + + DEBUGFUNC("ixgbe_identify_qsfp_module_generic"); + + if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_fiber_qsfp) { + hw->phy.sfp_type = ixgbe_sfp_type_not_present; + status = IXGBE_ERR_SFP_NOT_PRESENT; + goto out; + } + + /* LAN ID is needed for I2C access */ + hw->mac.ops.set_lan_id(hw); + + status = hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_IDENTIFIER, + &identifier); + + if (status != IXGBE_SUCCESS) + goto err_read_i2c_eeprom; + + if (identifier != IXGBE_SFF_IDENTIFIER_QSFP_PLUS) { + hw->phy.type = ixgbe_phy_sfp_unsupported; + status = IXGBE_ERR_SFP_NOT_SUPPORTED; + goto out; + } + + hw->phy.id = identifier; + + status = hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_QSFP_10GBE_COMP, + &comp_codes_10g); + + if (status != IXGBE_SUCCESS) + goto err_read_i2c_eeprom; + + status = hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_QSFP_1GBE_COMP, + &comp_codes_1g); + + if (status != IXGBE_SUCCESS) + goto err_read_i2c_eeprom; + + if (comp_codes_10g & IXGBE_SFF_QSFP_DA_PASSIVE_CABLE) { + hw->phy.type = ixgbe_phy_qsfp_passive_unknown; + if (hw->bus.lan_id == 0) + hw->phy.sfp_type = ixgbe_sfp_type_da_cu_core0; + else + hw->phy.sfp_type = ixgbe_sfp_type_da_cu_core1; + } else if (comp_codes_10g & (IXGBE_SFF_10GBASESR_CAPABLE | + IXGBE_SFF_10GBASELR_CAPABLE)) { + if (hw->bus.lan_id == 0) + hw->phy.sfp_type = ixgbe_sfp_type_srlr_core0; + else + hw->phy.sfp_type = ixgbe_sfp_type_srlr_core1; + } else { + if (comp_codes_10g & IXGBE_SFF_QSFP_DA_ACTIVE_CABLE) + active_cable = TRUE; + + if (!active_cable) { + /* check for active DA cables that pre-date + * SFF-8436 v3.6 */ + hw->phy.ops.read_i2c_eeprom(hw, + IXGBE_SFF_QSFP_CONNECTOR, + &connector); + + hw->phy.ops.read_i2c_eeprom(hw, + IXGBE_SFF_QSFP_CABLE_LENGTH, + &cable_length); + + hw->phy.ops.read_i2c_eeprom(hw, + IXGBE_SFF_QSFP_DEVICE_TECH, + &device_tech); + + if ((connector == + IXGBE_SFF_QSFP_CONNECTOR_NOT_SEPARABLE) && + (cable_length > 0) && + ((device_tech >> 4) == + IXGBE_SFF_QSFP_TRANSMITER_850NM_VCSEL)) + active_cable = TRUE; + } + + if (active_cable) { + hw->phy.type = ixgbe_phy_qsfp_active_unknown; + if (hw->bus.lan_id == 0) + hw->phy.sfp_type = + ixgbe_sfp_type_da_act_lmt_core0; + else + hw->phy.sfp_type = + ixgbe_sfp_type_da_act_lmt_core1; + } else { + /* unsupported module type */ + hw->phy.type = ixgbe_phy_sfp_unsupported; + status = IXGBE_ERR_SFP_NOT_SUPPORTED; + goto out; + } + } + + if (hw->phy.sfp_type != stored_sfp_type) + hw->phy.sfp_setup_needed = TRUE; + + /* Determine if the QSFP+ PHY is dual speed or not. */ + hw->phy.multispeed_fiber = FALSE; + if (((comp_codes_1g & IXGBE_SFF_1GBASESX_CAPABLE) && + (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE)) || + ((comp_codes_1g & IXGBE_SFF_1GBASELX_CAPABLE) && + (comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE))) + hw->phy.multispeed_fiber = TRUE; + + /* Determine PHY vendor for optical modules */ + if (comp_codes_10g & (IXGBE_SFF_10GBASESR_CAPABLE | + IXGBE_SFF_10GBASELR_CAPABLE)) { + status = hw->phy.ops.read_i2c_eeprom(hw, + IXGBE_SFF_QSFP_VENDOR_OUI_BYTE0, + &oui_bytes[0]); + + if (status != IXGBE_SUCCESS) + goto err_read_i2c_eeprom; + + status = hw->phy.ops.read_i2c_eeprom(hw, + IXGBE_SFF_QSFP_VENDOR_OUI_BYTE1, + &oui_bytes[1]); + + if (status != IXGBE_SUCCESS) + goto err_read_i2c_eeprom; + + status = hw->phy.ops.read_i2c_eeprom(hw, + IXGBE_SFF_QSFP_VENDOR_OUI_BYTE2, + &oui_bytes[2]); + + if (status != IXGBE_SUCCESS) + goto err_read_i2c_eeprom; + + vendor_oui = + ((oui_bytes[0] << IXGBE_SFF_VENDOR_OUI_BYTE0_SHIFT) | + (oui_bytes[1] << IXGBE_SFF_VENDOR_OUI_BYTE1_SHIFT) | + (oui_bytes[2] << IXGBE_SFF_VENDOR_OUI_BYTE2_SHIFT)); + + if (vendor_oui == IXGBE_SFF_VENDOR_OUI_INTEL) + hw->phy.type = ixgbe_phy_qsfp_intel; + else + hw->phy.type = ixgbe_phy_qsfp_unknown; + + /* + * We do not limit the definition of "supported SPF modules" + * to the vendor/make whitelist. + */ + status = IXGBE_SUCCESS; + } + +out: + return status; + +err_read_i2c_eeprom: + hw->phy.sfp_type = ixgbe_sfp_type_not_present; + hw->phy.id = 0; + hw->phy.type = ixgbe_phy_unknown; + + return IXGBE_ERR_SFP_NOT_PRESENT; +} + + +/** * ixgbe_get_sfp_init_sequence_offsets - Provides offset of PHY init sequence * @hw: pointer to hardware structure * @list_offset: offset to the SFP ID list @@ -1377,6 +1766,21 @@ int32_t ixgbe_write_i2c_eeprom_generic(struct ixgbe_hw *hw, uint8_t byte_offset, } /** + * ixgbe_is_sfp_probe - Returns TRUE if SFP is being detected + * @hw: pointer to hardware structure + * @offset: eeprom offset to be read + * @addr: I2C address to be read + */ +bool ixgbe_is_sfp_probe(struct ixgbe_hw *hw, uint8_t offset, uint8_t addr) +{ + if (addr == IXGBE_I2C_EEPROM_DEV_ADDR && + offset == IXGBE_SFF_IDENTIFIER && + hw->phy.sfp_type == ixgbe_sfp_type_not_present) + return TRUE; + return FALSE; +} + +/** * ixgbe_read_i2c_byte_generic - Reads 8 bit word over I2C * @hw: pointer to hardware structure * @byte_offset: byte offset to read @@ -1930,3 +2334,36 @@ int32_t ixgbe_tn_check_overtemp(struct ixgbe_hw *hw) out: return status; } + +/** + * ixgbe_set_copper_phy_power - Control power for copper phy + * @hw: pointer to hardware structure + * @on: TRUE for on, FALSE for off + */ +int32_t ixgbe_set_copper_phy_power(struct ixgbe_hw *hw, bool on) +{ + uint32_t status; + uint16_t reg; + + if (!on && ixgbe_mng_present(hw)) + return 0; + + status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_VENDOR_SPECIFIC_1_CONTROL, + IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, + ®); + if (status) + return status; + + if (on) { + reg &= ~IXGBE_MDIO_PHY_SET_LOW_POWER_MODE; + } else { + if (ixgbe_check_reset_blocked(hw)) + return 0; + reg |= IXGBE_MDIO_PHY_SET_LOW_POWER_MODE; + } + + status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_VENDOR_SPECIFIC_1_CONTROL, + IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, + reg); + return status; +} diff --git a/sys/dev/pci/ixgbe_type.h b/sys/dev/pci/ixgbe_type.h index ce91ec495bf..47eb87c6aaf 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.25 2016/11/16 23:19:29 mikeb Exp $ */ +/* $OpenBSD: ixgbe_type.h,v 1.26 2016/11/17 19:26:57 mikeb Exp $ */ /****************************************************************************** @@ -3414,9 +3414,11 @@ struct ixgbe_mac_operations { void (*enable_tx_laser)(struct ixgbe_hw *); void (*flap_tx_laser)(struct ixgbe_hw *); int32_t (*setup_link)(struct ixgbe_hw *, ixgbe_link_speed, bool); + int32_t (*setup_mac_link)(struct ixgbe_hw *, ixgbe_link_speed, bool); int32_t (*check_link)(struct ixgbe_hw *, ixgbe_link_speed *, bool *, bool); int32_t (*get_link_capabilities)(struct ixgbe_hw *, ixgbe_link_speed *, bool *); + void (*set_rate_select_speed)(struct ixgbe_hw *, ixgbe_link_speed); /* LED */ int32_t (*led_on)(struct ixgbe_hw *, uint32_t); @@ -3444,6 +3446,11 @@ struct ixgbe_mac_operations { /* Flow Control */ int32_t (*fc_enable)(struct ixgbe_hw *); + int32_t (*setup_fc)(struct ixgbe_hw *); + + /* Manageability interface */ + void (*disable_rx)(struct ixgbe_hw *hw); + void (*enable_rx)(struct ixgbe_hw *hw); /* Misc */ bool (*verify_lesm_fw_enabled)(struct ixgbe_hw *); @@ -3461,6 +3468,7 @@ struct ixgbe_phy_operations { int32_t (*read_reg_mdi)(struct ixgbe_hw *, uint32_t, uint32_t, uint16_t *); int32_t (*write_reg_mdi)(struct ixgbe_hw *, uint32_t, uint32_t, uint16_t); int32_t (*setup_link)(struct ixgbe_hw *); + int32_t (*setup_internal_link)(struct ixgbe_hw *); int32_t (*setup_link_speed)(struct ixgbe_hw *, ixgbe_link_speed, bool); int32_t (*check_link)(struct ixgbe_hw *, ixgbe_link_speed *, bool *); int32_t (*get_firmware_version)(struct ixgbe_hw *, uint16_t *); @@ -3470,6 +3478,7 @@ struct ixgbe_phy_operations { int32_t (*write_i2c_eeprom)(struct ixgbe_hw *, uint8_t, uint8_t); void (*i2c_bus_clear)(struct ixgbe_hw *); int32_t (*check_overtemp)(struct ixgbe_hw *); + int32_t (*set_phy_power)(struct ixgbe_hw *, bool on); }; struct ixgbe_eeprom_info { diff --git a/sys/dev/pci/ixgbe_x540.c b/sys/dev/pci/ixgbe_x540.c index 41c0530c54c..511d7bf7345 100644 --- a/sys/dev/pci/ixgbe_x540.c +++ b/sys/dev/pci/ixgbe_x540.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ixgbe_x540.c,v 1.6 2016/11/17 12:21:27 mikeb Exp $ */ +/* $OpenBSD: ixgbe_x540.c,v 1.7 2016/11/17 19:26:57 mikeb Exp $ */ /****************************************************************************** @@ -99,6 +99,7 @@ int32_t ixgbe_init_ops_X540(struct ixgbe_hw *hw) /* PHY */ phy->ops.init = ixgbe_init_phy_ops_generic; phy->ops.reset = NULL; + phy->ops.set_phy_power = ixgbe_set_copper_phy_power; /* MAC */ mac->ops.reset_hw = ixgbe_reset_hw_X540; @@ -132,8 +133,8 @@ int32_t ixgbe_init_ops_X540(struct ixgbe_hw *hw) mac->vft_size = IXGBE_X540_VFT_TBL_SIZE; mac->num_rar_entries = IXGBE_X540_RAR_ENTRIES; mac->rx_pb_size = IXGBE_X540_RX_PB_SIZE; - mac->max_tx_queues = IXGBE_X540_MAX_TX_QUEUES; mac->max_rx_queues = IXGBE_X540_MAX_RX_QUEUES; + mac->max_tx_queues = IXGBE_X540_MAX_TX_QUEUES; mac->max_msix_vectors = 0 /*ixgbe_get_pcie_msix_count_generic(hw)*/; hw->mbx.ops.init_params = ixgbe_init_mbx_params_pf; @@ -465,8 +466,7 @@ int32_t ixgbe_validate_eeprom_checksum_X540(struct ixgbe_hw *hw, DEBUGFUNC("ixgbe_validate_eeprom_checksum_X540"); - /* - * Read the first word from the EEPROM. If this times out or fails, do + /* 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 */ @@ -562,7 +562,7 @@ int32_t ixgbe_update_eeprom_checksum_X540(struct ixgbe_hw *hw) int32_t ixgbe_update_flash_X540(struct ixgbe_hw *hw) { uint32_t flup; - int32_t status = IXGBE_ERR_EEPROM; + int32_t status; DEBUGFUNC("ixgbe_update_flash_X540"); @@ -620,7 +620,7 @@ int32_t ixgbe_poll_flash_update_done_X540(struct ixgbe_hw *hw) status = IXGBE_SUCCESS; break; } - usec_delay(5); + msec_delay(5); } return status; } |