diff options
Diffstat (limited to 'drivers/net/ixgbe/ixgbe_common.c')
-rw-r--r-- | drivers/net/ixgbe/ixgbe_common.c | 138 |
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 | **/ | ||
1496 | s32 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 | |||
1623 | out: | ||
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 | * |