ixgbe: support link speed auto-negotiation on X550em_x

Normally the auto-negotiation is supported by FW. SW need not care about
that. But on x550em_x, FW doesn't support auto-neg. As the x550em_x ports
are 10G, if we connect the port will a peer which is 1G, the link will
always be down.
We need support auto-neg by SW to avoid this link down issue. As we already
have the code to handle the link speed setting, what we need is a trigger.
When the advertised link speed changes, a PHY interruption will be
triggered. So, we should handle this interrupt and call ixgbe_handle_lasi
to set the link speed correctly.

Please be aware it's working when auto-neg is on. If the auto-neg of the
peer port is turned off and its speed is indicated manually, we should also
set the speed of our own port manually.

Signed-off-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
Acked-by: Shaopeng He <shaopeng.he@intel.com>
This commit is contained in:
Wenzhuo Lu 2016-02-26 11:05:29 +08:00 committed by Thomas Monjalon
parent 72dec9e37a
commit 6be3dfec31
3 changed files with 47 additions and 0 deletions

View File

@ -116,6 +116,14 @@ This section should contain new features added in this release. Sample format:
Only x550em_x V1 was supported before. Now V2 is supported.
A mask for V1 and V2 is defined and used to support both.
* **Supported link speed auto-negotiation on X550EM_X**
Normally the auto-negotiation is supported by FW. SW need not care about
that. But on x550em_x, FW doesn't support auto-neg. As the ports of x550em_x
are 10G, if we connect the port with a peer which is 1G, the link will always
be down.
We added the support of auto-neg by SW to avoid this link down issue.
* **Added sw-firmware sync on X550EM_a.**
Added support for sw-firmware sync for resource sharing.

View File

@ -2030,6 +2030,25 @@ ixgbe_dev_configure(struct rte_eth_dev *dev)
return 0;
}
static void
ixgbe_dev_phy_intr_setup(struct rte_eth_dev *dev)
{
struct ixgbe_hw *hw =
IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
struct ixgbe_interrupt *intr =
IXGBE_DEV_PRIVATE_TO_INTR(dev->data->dev_private);
uint32_t gpie;
/* only set up it on X550EM_X */
if (hw->mac.type == ixgbe_mac_X550EM_x) {
gpie = IXGBE_READ_REG(hw, IXGBE_GPIE);
gpie |= IXGBE_SDP0_GPIEN_X550EM_x;
IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie);
if (hw->phy.type == ixgbe_phy_x550em_ext_t)
intr->mask |= IXGBE_EICR_GPI_SDP0_X550EM_x;
}
}
/*
* Configure device link speed and setup link.
* It returns 0 on success.
@ -2078,6 +2097,8 @@ ixgbe_dev_start(struct rte_eth_dev *dev)
/* configure PF module if SRIOV enabled */
ixgbe_pf_host_configure(dev);
ixgbe_dev_phy_intr_setup(dev);
/* check and configure queue intr-vector mapping */
if ((rte_intr_cap_multiple(intr_handle) ||
!RTE_ETH_DEV_SRIOV(dev).active) &&
@ -3156,6 +3177,11 @@ ixgbe_dev_interrupt_get_status(struct rte_eth_dev *dev)
if (eicr & IXGBE_EICR_MAILBOX)
intr->flags |= IXGBE_FLAG_MAILBOX;
if (hw->mac.type == ixgbe_mac_X550EM_x &&
hw->phy.type == ixgbe_phy_x550em_ext_t &&
(eicr & IXGBE_EICR_GPI_SDP0_X550EM_x))
intr->flags |= IXGBE_FLAG_PHY_INTERRUPT;
return 0;
}
@ -3211,6 +3237,8 @@ ixgbe_dev_interrupt_action(struct rte_eth_dev *dev)
int64_t timeout;
struct rte_eth_link link;
int intr_enable_delay = false;
struct ixgbe_hw *hw =
IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
PMD_DRV_LOG(DEBUG, "intr action type %d", intr->flags);
@ -3219,6 +3247,11 @@ ixgbe_dev_interrupt_action(struct rte_eth_dev *dev)
intr->flags &= ~IXGBE_FLAG_MAILBOX;
}
if (intr->flags & IXGBE_FLAG_PHY_INTERRUPT) {
ixgbe_handle_lasi(hw);
intr->flags &= ~IXGBE_FLAG_PHY_INTERRUPT;
}
if (intr->flags & IXGBE_FLAG_NEED_LINK_UPDATE) {
/* get the link status before link update, for predicting later */
memset(&link, 0, sizeof(link));
@ -3282,6 +3315,11 @@ ixgbe_dev_interrupt_delayed_handler(void *param)
if (eicr & IXGBE_EICR_MAILBOX)
ixgbe_pf_mbx_process(dev);
if (intr->flags & IXGBE_FLAG_PHY_INTERRUPT) {
ixgbe_handle_lasi(hw);
intr->flags &= ~IXGBE_FLAG_PHY_INTERRUPT;
}
if (intr->flags & IXGBE_FLAG_NEED_LINK_UPDATE) {
ixgbe_dev_link_update(dev, 0);
intr->flags &= ~IXGBE_FLAG_NEED_LINK_UPDATE;

View File

@ -42,6 +42,7 @@
/* need update link, bit flag */
#define IXGBE_FLAG_NEED_LINK_UPDATE (uint32_t)(1 << 0)
#define IXGBE_FLAG_MAILBOX (uint32_t)(1 << 1)
#define IXGBE_FLAG_PHY_INTERRUPT (uint32_t)(1 << 2)
/*
* Defines that were not part of ixgbe_type.h as they are not used by the