aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ixgbe/ixgbe_common.c
diff options
context:
space:
mode:
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 *