diff options
Diffstat (limited to 'drivers/net/ethernet/qualcomm/emac')
-rw-r--r-- | drivers/net/ethernet/qualcomm/emac/emac-ethtool.c | 94 | ||||
-rw-r--r-- | drivers/net/ethernet/qualcomm/emac/emac-mac.c | 70 | ||||
-rw-r--r-- | drivers/net/ethernet/qualcomm/emac/emac.c | 11 | ||||
-rw-r--r-- | drivers/net/ethernet/qualcomm/emac/emac.h | 115 |
4 files changed, 191 insertions, 99 deletions
diff --git a/drivers/net/ethernet/qualcomm/emac/emac-ethtool.c b/drivers/net/ethernet/qualcomm/emac/emac-ethtool.c index cfc57d2c64f9..bbe24639aa5a 100644 --- a/drivers/net/ethernet/qualcomm/emac/emac-ethtool.c +++ b/drivers/net/ethernet/qualcomm/emac/emac-ethtool.c @@ -145,19 +145,89 @@ static void emac_get_ringparam(struct net_device *netdev, ring->tx_pending = adpt->tx_desc_cnt; } +static int emac_set_ringparam(struct net_device *netdev, + struct ethtool_ringparam *ring) +{ + struct emac_adapter *adpt = netdev_priv(netdev); + + /* We don't have separate queues/rings for small/large frames, so + * reject any attempt to specify those values separately. + */ + if (ring->rx_mini_pending || ring->rx_jumbo_pending) + return -EINVAL; + + adpt->tx_desc_cnt = + clamp_val(ring->tx_pending, EMAC_MIN_TX_DESCS, EMAC_MAX_TX_DESCS); + + adpt->rx_desc_cnt = + clamp_val(ring->rx_pending, EMAC_MIN_RX_DESCS, EMAC_MAX_RX_DESCS); + + if (netif_running(netdev)) + return emac_reinit_locked(adpt); + + return 0; +} + static void emac_get_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *pause) { - struct phy_device *phydev = netdev->phydev; + struct emac_adapter *adpt = netdev_priv(netdev); - if (phydev) { - if (phydev->autoneg) - pause->autoneg = 1; - if (phydev->pause) - pause->rx_pause = 1; - if (phydev->pause != phydev->asym_pause) - pause->tx_pause = 1; - } + pause->autoneg = adpt->automatic ? AUTONEG_ENABLE : AUTONEG_DISABLE; + pause->rx_pause = adpt->rx_flow_control ? 1 : 0; + pause->tx_pause = adpt->tx_flow_control ? 1 : 0; +} + +static int emac_set_pauseparam(struct net_device *netdev, + struct ethtool_pauseparam *pause) +{ + struct emac_adapter *adpt = netdev_priv(netdev); + + adpt->automatic = pause->autoneg == AUTONEG_ENABLE; + adpt->rx_flow_control = pause->rx_pause != 0; + adpt->tx_flow_control = pause->tx_pause != 0; + + if (netif_running(netdev)) + return emac_reinit_locked(adpt); + + return 0; +} + +/* Selected registers that might want to track during runtime. */ +static const u16 emac_regs[] = { + EMAC_DMA_MAS_CTRL, + EMAC_MAC_CTRL, + EMAC_TXQ_CTRL_0, + EMAC_RXQ_CTRL_0, + EMAC_DMA_CTRL, + EMAC_INT_MASK, + EMAC_AXI_MAST_CTRL, + EMAC_CORE_HW_VERSION, + EMAC_MISC_CTRL, +}; + +/* Every time emac_regs[] above is changed, increase this version number. */ +#define EMAC_REGS_VERSION 0 + +#define EMAC_MAX_REG_SIZE ARRAY_SIZE(emac_regs) + +static void emac_get_regs(struct net_device *netdev, + struct ethtool_regs *regs, void *buff) +{ + struct emac_adapter *adpt = netdev_priv(netdev); + u32 *val = buff; + unsigned int i; + + regs->version = EMAC_REGS_VERSION; + regs->len = EMAC_MAX_REG_SIZE * sizeof(u32); + + for (i = 0; i < EMAC_MAX_REG_SIZE; i++) + val[i] = readl(adpt->base + emac_regs[i]); +} + +static int emac_get_regs_len(struct net_device *netdev) +{ + return EMAC_MAX_REG_SIZE * sizeof(u32); } static const struct ethtool_ops emac_ethtool_ops = { @@ -172,11 +242,17 @@ static const struct ethtool_ops emac_ethtool_ops = { .get_ethtool_stats = emac_get_ethtool_stats, .get_ringparam = emac_get_ringparam, + .set_ringparam = emac_set_ringparam, + .get_pauseparam = emac_get_pauseparam, + .set_pauseparam = emac_set_pauseparam, .nway_reset = emac_nway_reset, .get_link = ethtool_op_get_link, + + .get_regs_len = emac_get_regs_len, + .get_regs = emac_get_regs, }; void emac_set_ethtool_ops(struct net_device *netdev) diff --git a/drivers/net/ethernet/qualcomm/emac/emac-mac.c b/drivers/net/ethernet/qualcomm/emac/emac-mac.c index b991219862b1..cc065ffbe4b5 100644 --- a/drivers/net/ethernet/qualcomm/emac/emac-mac.c +++ b/drivers/net/ethernet/qualcomm/emac/emac-mac.c @@ -25,58 +25,6 @@ #include "emac.h" #include "emac-sgmii.h" -/* EMAC base register offsets */ -#define EMAC_MAC_CTRL 0x001480 -#define EMAC_WOL_CTRL0 0x0014a0 -#define EMAC_RSS_KEY0 0x0014b0 -#define EMAC_H1TPD_BASE_ADDR_LO 0x0014e0 -#define EMAC_H2TPD_BASE_ADDR_LO 0x0014e4 -#define EMAC_H3TPD_BASE_ADDR_LO 0x0014e8 -#define EMAC_INTER_SRAM_PART9 0x001534 -#define EMAC_DESC_CTRL_0 0x001540 -#define EMAC_DESC_CTRL_1 0x001544 -#define EMAC_DESC_CTRL_2 0x001550 -#define EMAC_DESC_CTRL_10 0x001554 -#define EMAC_DESC_CTRL_12 0x001558 -#define EMAC_DESC_CTRL_13 0x00155c -#define EMAC_DESC_CTRL_3 0x001560 -#define EMAC_DESC_CTRL_4 0x001564 -#define EMAC_DESC_CTRL_5 0x001568 -#define EMAC_DESC_CTRL_14 0x00156c -#define EMAC_DESC_CTRL_15 0x001570 -#define EMAC_DESC_CTRL_16 0x001574 -#define EMAC_DESC_CTRL_6 0x001578 -#define EMAC_DESC_CTRL_8 0x001580 -#define EMAC_DESC_CTRL_9 0x001584 -#define EMAC_DESC_CTRL_11 0x001588 -#define EMAC_TXQ_CTRL_0 0x001590 -#define EMAC_TXQ_CTRL_1 0x001594 -#define EMAC_TXQ_CTRL_2 0x001598 -#define EMAC_RXQ_CTRL_0 0x0015a0 -#define EMAC_RXQ_CTRL_1 0x0015a4 -#define EMAC_RXQ_CTRL_2 0x0015a8 -#define EMAC_RXQ_CTRL_3 0x0015ac -#define EMAC_BASE_CPU_NUMBER 0x0015b8 -#define EMAC_DMA_CTRL 0x0015c0 -#define EMAC_MAILBOX_0 0x0015e0 -#define EMAC_MAILBOX_5 0x0015e4 -#define EMAC_MAILBOX_6 0x0015e8 -#define EMAC_MAILBOX_13 0x0015ec -#define EMAC_MAILBOX_2 0x0015f4 -#define EMAC_MAILBOX_3 0x0015f8 -#define EMAC_MAILBOX_11 0x00160c -#define EMAC_AXI_MAST_CTRL 0x001610 -#define EMAC_MAILBOX_12 0x001614 -#define EMAC_MAILBOX_9 0x001618 -#define EMAC_MAILBOX_10 0x00161c -#define EMAC_ATHR_HEADER_CTRL 0x001620 -#define EMAC_CLK_GATE_CTRL 0x001814 -#define EMAC_MISC_CTRL 0x001990 -#define EMAC_MAILBOX_7 0x0019e0 -#define EMAC_MAILBOX_8 0x0019e4 -#define EMAC_MAILBOX_15 0x001bd4 -#define EMAC_MAILBOX_16 0x001bd8 - /* EMAC_MAC_CTRL */ #define SINGLE_PAUSE_MODE 0x10000000 #define DEBUG_MODE 0x08000000 @@ -565,11 +513,19 @@ static void emac_mac_start(struct emac_adapter *adpt) mac |= TXEN | RXEN; /* enable RX/TX */ - /* Configure MAC flow control to match the PHY's settings. */ - if (phydev->pause) - mac |= RXFC; - if (phydev->pause != phydev->asym_pause) - mac |= TXFC; + /* Configure MAC flow control. If set to automatic, then match + * whatever the PHY does. Otherwise, enable or disable it, depending + * on what the user configured via ethtool. + */ + mac &= ~(RXFC | TXFC); + + if (adpt->automatic) { + /* If it's set to automatic, then update our local values */ + adpt->rx_flow_control = phydev->pause; + adpt->tx_flow_control = phydev->pause != phydev->asym_pause; + } + mac |= adpt->rx_flow_control ? RXFC : 0; + mac |= adpt->tx_flow_control ? TXFC : 0; /* setup link speed */ mac &= ~SPEED_MASK; diff --git a/drivers/net/ethernet/qualcomm/emac/emac.c b/drivers/net/ethernet/qualcomm/emac/emac.c index 3387c0a88746..28a8cdc36485 100644 --- a/drivers/net/ethernet/qualcomm/emac/emac.c +++ b/drivers/net/ethernet/qualcomm/emac/emac.c @@ -436,6 +436,10 @@ static void emac_init_adapter(struct emac_adapter *adpt) { u32 reg; + adpt->rrd_size = EMAC_RRD_SIZE; + adpt->tpd_size = EMAC_TPD_SIZE; + adpt->rfd_size = EMAC_RFD_SIZE; + /* descriptors */ adpt->tx_desc_cnt = EMAC_DEF_TX_DESCS; adpt->rx_desc_cnt = EMAC_DEF_RX_DESCS; @@ -456,6 +460,9 @@ static void emac_init_adapter(struct emac_adapter *adpt) /* others */ adpt->preamble = EMAC_PREAMBLE_DEF; + + /* default to automatic flow control */ + adpt->automatic = true; } /* Get the clock */ @@ -675,10 +682,6 @@ static int emac_probe(struct platform_device *pdev) netdev->watchdog_timeo = EMAC_WATCHDOG_TIME; netdev->irq = adpt->irq.irq; - adpt->rrd_size = EMAC_RRD_SIZE; - adpt->tpd_size = EMAC_TPD_SIZE; - adpt->rfd_size = EMAC_RFD_SIZE; - netdev->netdev_ops = &emac_netdev_ops; emac_init_adapter(adpt); diff --git a/drivers/net/ethernet/qualcomm/emac/emac.h b/drivers/net/ethernet/qualcomm/emac/emac.h index ef91dcc7f646..8ee4ec6aef2e 100644 --- a/drivers/net/ethernet/qualcomm/emac/emac.h +++ b/drivers/net/ethernet/qualcomm/emac/emac.h @@ -22,35 +22,85 @@ #include "emac-sgmii.h" /* EMAC base register offsets */ -#define EMAC_DMA_MAS_CTRL 0x001400 -#define EMAC_IRQ_MOD_TIM_INIT 0x001408 -#define EMAC_BLK_IDLE_STS 0x00140c -#define EMAC_PHY_LINK_DELAY 0x00141c -#define EMAC_SYS_ALIV_CTRL 0x001434 -#define EMAC_MAC_IPGIFG_CTRL 0x001484 -#define EMAC_MAC_STA_ADDR0 0x001488 -#define EMAC_MAC_STA_ADDR1 0x00148c -#define EMAC_HASH_TAB_REG0 0x001490 -#define EMAC_HASH_TAB_REG1 0x001494 -#define EMAC_MAC_HALF_DPLX_CTRL 0x001498 -#define EMAC_MAX_FRAM_LEN_CTRL 0x00149c -#define EMAC_INT_STATUS 0x001600 -#define EMAC_INT_MASK 0x001604 -#define EMAC_RXMAC_STATC_REG0 0x001700 -#define EMAC_RXMAC_STATC_REG22 0x001758 -#define EMAC_TXMAC_STATC_REG0 0x001760 -#define EMAC_TXMAC_STATC_REG24 0x0017c0 -#define EMAC_CORE_HW_VERSION 0x001974 -#define EMAC_IDT_TABLE0 0x001b00 -#define EMAC_RXMAC_STATC_REG23 0x001bc8 -#define EMAC_RXMAC_STATC_REG24 0x001bcc -#define EMAC_TXMAC_STATC_REG25 0x001bd0 -#define EMAC_INT1_MASK 0x001bf0 -#define EMAC_INT1_STATUS 0x001bf4 -#define EMAC_INT2_MASK 0x001bf8 -#define EMAC_INT2_STATUS 0x001bfc -#define EMAC_INT3_MASK 0x001c00 -#define EMAC_INT3_STATUS 0x001c04 +#define EMAC_DMA_MAS_CTRL 0x1400 +#define EMAC_IRQ_MOD_TIM_INIT 0x1408 +#define EMAC_BLK_IDLE_STS 0x140c +#define EMAC_PHY_LINK_DELAY 0x141c +#define EMAC_SYS_ALIV_CTRL 0x1434 +#define EMAC_MAC_CTRL 0x1480 +#define EMAC_MAC_IPGIFG_CTRL 0x1484 +#define EMAC_MAC_STA_ADDR0 0x1488 +#define EMAC_MAC_STA_ADDR1 0x148c +#define EMAC_HASH_TAB_REG0 0x1490 +#define EMAC_HASH_TAB_REG1 0x1494 +#define EMAC_MAC_HALF_DPLX_CTRL 0x1498 +#define EMAC_MAX_FRAM_LEN_CTRL 0x149c +#define EMAC_WOL_CTRL0 0x14a0 +#define EMAC_RSS_KEY0 0x14b0 +#define EMAC_H1TPD_BASE_ADDR_LO 0x14e0 +#define EMAC_H2TPD_BASE_ADDR_LO 0x14e4 +#define EMAC_H3TPD_BASE_ADDR_LO 0x14e8 +#define EMAC_INTER_SRAM_PART9 0x1534 +#define EMAC_DESC_CTRL_0 0x1540 +#define EMAC_DESC_CTRL_1 0x1544 +#define EMAC_DESC_CTRL_2 0x1550 +#define EMAC_DESC_CTRL_10 0x1554 +#define EMAC_DESC_CTRL_12 0x1558 +#define EMAC_DESC_CTRL_13 0x155c +#define EMAC_DESC_CTRL_3 0x1560 +#define EMAC_DESC_CTRL_4 0x1564 +#define EMAC_DESC_CTRL_5 0x1568 +#define EMAC_DESC_CTRL_14 0x156c +#define EMAC_DESC_CTRL_15 0x1570 +#define EMAC_DESC_CTRL_16 0x1574 +#define EMAC_DESC_CTRL_6 0x1578 +#define EMAC_DESC_CTRL_8 0x1580 +#define EMAC_DESC_CTRL_9 0x1584 +#define EMAC_DESC_CTRL_11 0x1588 +#define EMAC_TXQ_CTRL_0 0x1590 +#define EMAC_TXQ_CTRL_1 0x1594 +#define EMAC_TXQ_CTRL_2 0x1598 +#define EMAC_RXQ_CTRL_0 0x15a0 +#define EMAC_RXQ_CTRL_1 0x15a4 +#define EMAC_RXQ_CTRL_2 0x15a8 +#define EMAC_RXQ_CTRL_3 0x15ac +#define EMAC_BASE_CPU_NUMBER 0x15b8 +#define EMAC_DMA_CTRL 0x15c0 +#define EMAC_MAILBOX_0 0x15e0 +#define EMAC_MAILBOX_5 0x15e4 +#define EMAC_MAILBOX_6 0x15e8 +#define EMAC_MAILBOX_13 0x15ec +#define EMAC_MAILBOX_2 0x15f4 +#define EMAC_MAILBOX_3 0x15f8 +#define EMAC_INT_STATUS 0x1600 +#define EMAC_INT_MASK 0x1604 +#define EMAC_MAILBOX_11 0x160c +#define EMAC_AXI_MAST_CTRL 0x1610 +#define EMAC_MAILBOX_12 0x1614 +#define EMAC_MAILBOX_9 0x1618 +#define EMAC_MAILBOX_10 0x161c +#define EMAC_ATHR_HEADER_CTRL 0x1620 +#define EMAC_RXMAC_STATC_REG0 0x1700 +#define EMAC_RXMAC_STATC_REG22 0x1758 +#define EMAC_TXMAC_STATC_REG0 0x1760 +#define EMAC_TXMAC_STATC_REG24 0x17c0 +#define EMAC_CLK_GATE_CTRL 0x1814 +#define EMAC_CORE_HW_VERSION 0x1974 +#define EMAC_MISC_CTRL 0x1990 +#define EMAC_MAILBOX_7 0x19e0 +#define EMAC_MAILBOX_8 0x19e4 +#define EMAC_IDT_TABLE0 0x1b00 +#define EMAC_RXMAC_STATC_REG23 0x1bc8 +#define EMAC_RXMAC_STATC_REG24 0x1bcc +#define EMAC_TXMAC_STATC_REG25 0x1bd0 +#define EMAC_MAILBOX_15 0x1bd4 +#define EMAC_MAILBOX_16 0x1bd8 +#define EMAC_INT1_MASK 0x1bf0 +#define EMAC_INT1_STATUS 0x1bf4 +#define EMAC_INT2_MASK 0x1bf8 +#define EMAC_INT2_STATUS 0x1bfc +#define EMAC_INT3_MASK 0x1c00 +#define EMAC_INT3_STATUS 0x1c04 /* EMAC_DMA_MAS_CTRL */ #define DEV_ID_NUM_BMSK 0x7f000000 @@ -306,6 +356,13 @@ struct emac_adapter { unsigned int rxbuf_size; + /* Flow control / pause frames support. If automatic=True, do whatever + * the PHY does. Otherwise, use tx_flow_control and rx_flow_control. + */ + bool automatic; + bool tx_flow_control; + bool rx_flow_control; + /* Ring parameter */ u8 tpd_burst; u8 rfd_burst; |