aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ixgbe/ixgbe_common.c
diff options
context:
space:
mode:
authorPeter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com>2009-02-07 00:46:54 -0500
committerDavid S. Miller <davem@davemloft.net>2009-02-07 00:46:54 -0500
commit0ecc061d1967e9f2694502079e00d9d6e1e39072 (patch)
tree40a06f43717f97d6dade8fbb55bad15740033799 /drivers/net/ixgbe/ixgbe_common.c
parent394827913e371b058849349c6fc9d52c59c31a3d (diff)
ixgbe: Update flow control state machine in link setup
The flow control handling is overly complicated and difficult to maintain. This patch cleans up the flow control handling and makes it much more explicit. It also adds 1G flow control autonegotiation, for 1G copper links, 1G KX links, and 1G fiber links. Signed-off-by: Peter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ixgbe/ixgbe_common.c')
-rw-r--r--drivers/net/ixgbe/ixgbe_common.c138
1 files changed, 138 insertions, 0 deletions
diff --git a/drivers/net/ixgbe/ixgbe_common.c b/drivers/net/ixgbe/ixgbe_common.c
index 13ad5ba66b63..5ae93989784f 100644
--- a/drivers/net/ixgbe/ixgbe_common.c
+++ b/drivers/net/ixgbe/ixgbe_common.c
@@ -1487,6 +1487,144 @@ s32 ixgbe_disable_mc_generic(struct ixgbe_hw *hw)
1487} 1487}
1488 1488
1489/** 1489/**
1490 * ixgbe_fc_autoneg - Configure flow control
1491 * @hw: pointer to hardware structure
1492 *
1493 * Negotiates flow control capabilities with link partner using autoneg and
1494 * applies the results.
1495 **/
1496s32 ixgbe_fc_autoneg(struct ixgbe_hw *hw)
1497{
1498 s32 ret_val = 0;
1499 u32 i, reg, pcs_anadv_reg, pcs_lpab_reg;
1500
1501 reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA);
1502
1503 /*
1504 * The possible values of fc.current_mode are:
1505 * 0: Flow control is completely disabled
1506 * 1: Rx flow control is enabled (we can receive pause frames,
1507 * but not send pause frames).
1508 * 2: Tx flow control is enabled (we can send pause frames but
1509 * we do not support receiving pause frames).
1510 * 3: Both Rx and Tx flow control (symmetric) are enabled.
1511 * other: Invalid.
1512 */
1513 switch (hw->fc.current_mode) {
1514 case ixgbe_fc_none:
1515 /* Flow control completely disabled by software override. */
1516 reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE);
1517 break;
1518 case ixgbe_fc_rx_pause:
1519 /*
1520 * Rx Flow control is enabled and Tx Flow control is
1521 * disabled by software override. Since there really
1522 * isn't a way to advertise that we are capable of RX
1523 * Pause ONLY, we will advertise that we support both
1524 * symmetric and asymmetric Rx PAUSE. Later, we will
1525 * disable the adapter's ability to send PAUSE frames.
1526 */
1527 reg |= (IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE);
1528 break;
1529 case ixgbe_fc_tx_pause:
1530 /*
1531 * Tx Flow control is enabled, and Rx Flow control is
1532 * disabled by software override.
1533 */
1534 reg |= (IXGBE_PCS1GANA_ASM_PAUSE);
1535 reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE);
1536 break;
1537 case ixgbe_fc_full:
1538 /* Flow control (both Rx and Tx) is enabled by SW override. */
1539 reg |= (IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE);
1540 break;
1541 default:
1542 hw_dbg(hw, "Flow control param set incorrectly\n");
1543 ret_val = -IXGBE_ERR_CONFIG;
1544 goto out;
1545 break;
1546 }
1547
1548 IXGBE_WRITE_REG(hw, IXGBE_PCS1GANA, reg);
1549 reg = IXGBE_READ_REG(hw, IXGBE_PCS1GLCTL);
1550
1551 /* Set PCS register for autoneg */
1552 /* Enable and restart autoneg */
1553 reg |= IXGBE_PCS1GLCTL_AN_ENABLE | IXGBE_PCS1GLCTL_AN_RESTART;
1554
1555 /* Disable AN timeout */
1556 if (hw->fc.strict_ieee)
1557 reg &= ~IXGBE_PCS1GLCTL_AN_1G_TIMEOUT_EN;
1558
1559 hw_dbg(hw, "Configuring Autoneg; PCS_LCTL = 0x%08X\n", reg);
1560 IXGBE_WRITE_REG(hw, IXGBE_PCS1GLCTL, reg);
1561
1562 /* See if autonegotiation has succeeded */
1563 hw->mac.autoneg_succeeded = 0;
1564 for (i = 0; i < FIBER_LINK_UP_LIMIT; i++) {
1565 msleep(10);
1566 reg = IXGBE_READ_REG(hw, IXGBE_PCS1GLSTA);
1567 if ((reg & (IXGBE_PCS1GLSTA_LINK_OK |
1568 IXGBE_PCS1GLSTA_AN_COMPLETE)) ==
1569 (IXGBE_PCS1GLSTA_LINK_OK |
1570 IXGBE_PCS1GLSTA_AN_COMPLETE)) {
1571 if (!(reg & IXGBE_PCS1GLSTA_AN_TIMED_OUT))
1572 hw->mac.autoneg_succeeded = 1;
1573 break;
1574 }
1575 }
1576
1577 if (!hw->mac.autoneg_succeeded) {
1578 /* Autoneg failed to achieve a link, so we turn fc off */
1579 hw->fc.current_mode = ixgbe_fc_none;
1580 hw_dbg(hw, "Flow Control = NONE.\n");
1581 goto out;
1582 }
1583
1584 /*
1585 * Read the AN advertisement and LP ability registers and resolve
1586 * local flow control settings accordingly
1587 */
1588 pcs_anadv_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA);
1589 pcs_lpab_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANLP);
1590 if ((pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
1591 (pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE)) {
1592 /*
1593 * Now we need to check if the user selected Rx ONLY
1594 * of pause frames. In this case, we had to advertise
1595 * FULL flow control because we could not advertise RX
1596 * ONLY. Hence, we must now check to see if we need to
1597 * turn OFF the TRANSMISSION of PAUSE frames.
1598 */
1599 if (hw->fc.requested_mode == ixgbe_fc_full) {
1600 hw->fc.current_mode = ixgbe_fc_full;
1601 hw_dbg(hw, "Flow Control = FULL.\n");
1602 } else {
1603 hw->fc.current_mode = ixgbe_fc_rx_pause;
1604 hw_dbg(hw, "Flow Control = RX PAUSE frames only.\n");
1605 }
1606 } else if (!(pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
1607 (pcs_anadv_reg & IXGBE_PCS1GANA_ASM_PAUSE) &&
1608 (pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
1609 (pcs_lpab_reg & IXGBE_PCS1GANA_ASM_PAUSE)) {
1610 hw->fc.current_mode = ixgbe_fc_tx_pause;
1611 hw_dbg(hw, "Flow Control = TX PAUSE frames only.\n");
1612 } else if ((pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
1613 (pcs_anadv_reg & IXGBE_PCS1GANA_ASM_PAUSE) &&
1614 !(pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
1615 (pcs_lpab_reg & IXGBE_PCS1GANA_ASM_PAUSE)) {
1616 hw->fc.current_mode = ixgbe_fc_rx_pause;
1617 hw_dbg(hw, "Flow Control = RX PAUSE frames only.\n");
1618 } else {
1619 hw->fc.current_mode = ixgbe_fc_none;
1620 hw_dbg(hw, "Flow Control = NONE.\n");
1621 }
1622
1623out:
1624 return ret_val;
1625}
1626
1627/**
1490 * ixgbe_disable_pcie_master - Disable PCI-express master access 1628 * ixgbe_disable_pcie_master - Disable PCI-express master access
1491 * @hw: pointer to hardware structure 1629 * @hw: pointer to hardware structure
1492 * 1630 *