drivers: net: stmmac: rework core ISR to better manage PCS and PMT
authorGiuseppe CAVALLARO <peppe.cavallaro@st.com>
Fri, 24 Jun 2016 13:16:25 +0000 (15:16 +0200)
committerDavid S. Miller <davem@davemloft.net>
Tue, 28 Jun 2016 12:54:23 +0000 (08:54 -0400)
By default, all gmac cores disable the PCS block and always
enable the PMT.

Note that this is done in a different way by 3.x and 4.x cores.

With this rework, PCS and PMT interrupt masks can be driven by
parameters now moved inside the mac_device_info structure
and the settings follow what the HW capability register reports.

Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/stmicro/stmmac/common.h
drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
drivers/net/ethernet/stmicro/stmmac/dwmac4.h
drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
drivers/net/ethernet/stmicro/stmmac/stmmac.h
drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c

index 86eba2a7bbea0dd53b5f25b0c1070fbd10f980c4..51077a8dc1f54cd50db0ac0c92cab402cf7a14db 100644 (file)
@@ -529,6 +529,8 @@ struct mac_device_info {
        int unicast_filter_entries;
        int mcast_bits_log2;
        unsigned int rx_csum;
+       unsigned int pcs;
+       unsigned int pmt;
 };
 
 struct mac_device_info *dwmac1000_setup(void __iomem *ioaddr, int mcbins,
index e67136038e559c1cc520de8d60d0ba0b0767871a..ff3e5ab39bd0e5a293844354300b7b9281b24d41 100644 (file)
 #define GMAC_WAKEUP_FILTER     0x00000028      /* Wake-up Frame Filter */
 
 #define GMAC_INT_STATUS                0x00000038      /* interrupt status register */
-enum dwmac1000_irq_status {
-       lpiis_irq = 0x400,
-       time_stamp_irq = 0x0200,
-       mmc_rx_csum_offload_irq = 0x0080,
-       mmc_tx_irq = 0x0040,
-       mmc_rx_irq = 0x0020,
-       mmc_irq = 0x0010,
-       pmt_irq = 0x0008,
-};
-#define GMAC_INT_MASK          0x0000003c      /* interrupt mask register */
+#define GMAC_INT_STATUS_PMT    BIT(3)
+#define GMAC_INT_STATUS_MMCIS  BIT(4)
+#define GMAC_INT_STATUS_MMCRIS BIT(5)
+#define GMAC_INT_STATUS_MMCTIS BIT(6)
+#define GMAC_INT_STATUS_MMCCSUM        BIT(7)
+#define GMAC_INT_STATUS_TSTAMP BIT(9)
+#define GMAC_INT_STATUS_LPIIS  BIT(10)
+
+/* interrupt mask register */
+#define        GMAC_INT_MASK           0x0000003c
+#define        GMAC_INT_DISABLE_RGMII          BIT(0)
+#define        GMAC_INT_DISABLE_PCSLINK        BIT(1)
+#define        GMAC_INT_DISABLE_PCSAN          BIT(2)
+#define        GMAC_INT_DISABLE_PMT            BIT(3)
+#define        GMAC_INT_DISABLE_TIMESTAMP      BIT(9)
+#define        GMAC_INT_DISABLE_PCS    (GMAC_INT_DISABLE_RGMII | \
+                                GMAC_INT_DISABLE_PCSLINK | \
+                                GMAC_INT_DISABLE_PCSAN)
+#define        GMAC_INT_DEFAULT_MASK   (GMAC_INT_DISABLE_TIMESTAMP | \
+                                GMAC_INT_DISABLE_PCS)
 
 /* PMT Control and Status */
 #define GMAC_PMT               0x0000002c
index 9772a43c27efc0fc8d50ea039d028ae01b53745b..0d31f2f80d07bed742f864825fa7018004d396f9 100644 (file)
@@ -37,7 +37,10 @@ static void dwmac1000_core_init(struct mac_device_info *hw, int mtu)
 {
        void __iomem *ioaddr = hw->pcsr;
        u32 value = readl(ioaddr + GMAC_CONTROL);
+
+       /* Configure GMAC core */
        value |= GMAC_CORE_INIT;
+
        if (mtu > 1500)
                value |= GMAC_CONTROL_2K;
        if (mtu > 2000)
@@ -46,7 +49,14 @@ static void dwmac1000_core_init(struct mac_device_info *hw, int mtu)
        writel(value, ioaddr + GMAC_CONTROL);
 
        /* Mask GMAC interrupts */
-       writel(0x207, ioaddr + GMAC_INT_MASK);
+       value = GMAC_INT_DEFAULT_MASK;
+
+       if (hw->pmt)
+               value &= ~GMAC_INT_DISABLE_PMT;
+       if (hw->pcs)
+               value &= ~GMAC_INT_DISABLE_PCS;
+
+       writel(value, ioaddr + GMAC_INT_MASK);
 
 #ifdef STMMAC_VLAN_TAG_USED
        /* Tag detection without filtering */
@@ -283,20 +293,20 @@ static int dwmac1000_irq_status(struct mac_device_info *hw,
        int ret = 0;
 
        /* Not used events (e.g. MMC interrupts) are not handled. */
-       if ((intr_status & mmc_tx_irq))
+       if ((intr_status & GMAC_INT_STATUS_MMCTIS))
                x->mmc_tx_irq_n++;
-       if (unlikely(intr_status & mmc_rx_irq))
+       if (unlikely(intr_status & GMAC_INT_STATUS_MMCRIS))
                x->mmc_rx_irq_n++;
-       if (unlikely(intr_status & mmc_rx_csum_offload_irq))
+       if (unlikely(intr_status & GMAC_INT_STATUS_MMCCSUM))
                x->mmc_rx_csum_offload_irq_n++;
-       if (unlikely(intr_status & pmt_irq)) {
+       if (unlikely(intr_status & GMAC_INT_DISABLE_PMT)) {
                /* clear the PMT bits 5 and 6 by reading the PMT status reg */
                readl(ioaddr + GMAC_PMT);
                x->irq_receive_pmt_irq_n++;
        }
 
-       /* MAC trx/rx EEE LPI entry/exit interrupts */
-       if (intr_status & lpiis_irq) {
+       /* MAC tx/rx EEE LPI entry/exit interrupts */
+       if (intr_status & GMAC_INT_STATUS_LPIIS) {
                /* Clean LPI interrupt by reading the Reg 12 */
                ret = readl(ioaddr + LPI_CTRL_STATUS);
 
index 227fa20d10c1929ae4d436d4d8ec751aff70e086..6f4f5ce2511466e1b2547544b3010eaa07c3b706 100644 (file)
 #define GMAC_TX_FLOW_CTRL_PT_SHIFT     16
 
 /*  MAC Interrupt bitmap*/
+#define GMAC_INT_RGSMIIS               BIT(0)
+#define GMAC_INT_PCS_LINK              BIT(1)
+#define GMAC_INT_PCS_ANE               BIT(2)
+#define GMAC_INT_PCS_PHYIS             BIT(3)
 #define GMAC_INT_PMT_EN                        BIT(4)
 #define GMAC_INT_LPI_EN                        BIT(5)
 
+#define        GMAC_PCS_IRQ_DEFAULT    (GMAC_INT_RGSMIIS | GMAC_INT_PCS_LINK | \
+                                GMAC_INT_PCS_ANE)
+
+#define        GMAC_INT_DEFAULT_MASK   GMAC_INT_PMT_EN
+
 enum dwmac4_irq_status {
        time_stamp_irq = 0x00001000,
        mmc_rx_csum_offload_irq = 0x00000800,
index 207d8bb0c80bf7d66b013d9f4b224e3ecd9a0803..747f3cf1e20bd1275fda61011171f1252ac611f5 100644 (file)
@@ -35,7 +35,13 @@ static void dwmac4_core_init(struct mac_device_info *hw, int mtu)
        writel(value, ioaddr + GMAC_CONFIG);
 
        /* Mask GMAC interrupts */
-       writel(GMAC_INT_PMT_EN, ioaddr + GMAC_INT_EN);
+       value = GMAC_INT_DEFAULT_MASK;
+       if (hw->pmt)
+               value |= GMAC_INT_PMT_EN;
+       if (hw->pcs)
+               value |= GMAC_PCS_IRQ_DEFAULT;
+
+       writel(value, ioaddr + GMAC_INT_EN);
 }
 
 static void dwmac4_dump_regs(struct mac_device_info *hw)
index 59ae6088cd226aed73bd2aca25bff5fdd6ee3dde..8dc9056c100105aecf77754128f74913bd9b1524 100644 (file)
@@ -117,7 +117,6 @@ struct stmmac_priv {
        int eee_enabled;
        int eee_active;
        int tx_lpi_timer;
-       int pcs;
        unsigned int mode;
        int extend_desc;
        struct ptp_clock *ptp_clock;
index a5f4f46da42b26df25d1369c20a5b88724a5eae7..da2d9b5b740a91320ce8f05bc70997e13ad57421 100644 (file)
@@ -276,7 +276,8 @@ static int stmmac_ethtool_getsettings(struct net_device *dev,
        struct phy_device *phy = priv->phydev;
        int rc;
 
-       if ((priv->pcs & STMMAC_PCS_RGMII) || (priv->pcs & STMMAC_PCS_SGMII)) {
+       if (priv->hw->pcs & STMMAC_PCS_RGMII ||
+           priv->hw->pcs & STMMAC_PCS_SGMII) {
                struct rgmii_adv adv;
 
                if (!priv->xstats.pcs_link) {
@@ -361,7 +362,8 @@ static int stmmac_ethtool_setsettings(struct net_device *dev,
        struct phy_device *phy = priv->phydev;
        int rc;
 
-       if ((priv->pcs & STMMAC_PCS_RGMII) || (priv->pcs & STMMAC_PCS_SGMII)) {
+       if (priv->hw->pcs & STMMAC_PCS_RGMII ||
+           priv->hw->pcs & STMMAC_PCS_SGMII) {
                u32 mask = ADVERTISED_Autoneg | ADVERTISED_Pause;
 
                /* Only support ANE */
@@ -457,7 +459,7 @@ stmmac_get_pauseparam(struct net_device *netdev,
        pause->rx_pause = 0;
        pause->tx_pause = 0;
 
-       if (priv->pcs && priv->hw->mac->pcs_get_adv_lp) {
+       if (priv->hw->pcs && priv->hw->mac->pcs_get_adv_lp) {
                struct rgmii_adv adv_lp;
 
                pause->autoneg = 1;
@@ -487,7 +489,7 @@ stmmac_set_pauseparam(struct net_device *netdev,
        struct phy_device *phy = priv->phydev;
        int new_pause = FLOW_OFF;
 
-       if (priv->pcs && priv->hw->mac->pcs_get_adv_lp) {
+       if (priv->hw->pcs && priv->hw->mac->pcs_get_adv_lp) {
                struct rgmii_adv adv_lp;
 
                pause->autoneg = 1;
@@ -507,6 +509,7 @@ stmmac_set_pauseparam(struct net_device *netdev,
 
        priv->flow_ctrl = new_pause;
        phy->autoneg = pause->autoneg;
+
        if (phy->autoneg) {
                if (netif_running(netdev))
                        return phy_start_aneg(phy);
index 6c43d682517285b273e7b93b46d06c8feabeaeef..6142fce9ffac346398a50efc42687c03f3f02ddc 100644 (file)
@@ -285,8 +285,9 @@ bool stmmac_eee_init(struct stmmac_priv *priv)
        /* Using PCS we cannot dial with the phy registers at this stage
         * so we do not support extra feature like EEE.
         */
-       if ((priv->pcs == STMMAC_PCS_RGMII) || (priv->pcs == STMMAC_PCS_TBI) ||
-           (priv->pcs == STMMAC_PCS_RTBI))
+       if ((priv->hw->pcs == STMMAC_PCS_RGMII) ||
+           (priv->hw->pcs == STMMAC_PCS_TBI) ||
+           (priv->hw->pcs == STMMAC_PCS_RTBI))
                goto out;
 
        /* MAC core supports the EEE feature. */
@@ -799,10 +800,10 @@ static void stmmac_check_pcs_mode(struct stmmac_priv *priv)
                    (interface == PHY_INTERFACE_MODE_RGMII_RXID) ||
                    (interface == PHY_INTERFACE_MODE_RGMII_TXID)) {
                        pr_debug("STMMAC: PCS RGMII support enable\n");
-                       priv->pcs = STMMAC_PCS_RGMII;
+                       priv->hw->pcs = STMMAC_PCS_RGMII;
                } else if (interface == PHY_INTERFACE_MODE_SGMII) {
                        pr_debug("STMMAC: PCS SGMII support enable\n");
-                       priv->pcs = STMMAC_PCS_SGMII;
+                       priv->hw->pcs = STMMAC_PCS_SGMII;
                }
        }
 }
@@ -1714,7 +1715,7 @@ static int stmmac_hw_setup(struct net_device *dev, bool init_ptp)
                priv->hw->dma->rx_watchdog(priv->ioaddr, MAX_DMA_RIWT);
        }
 
-       if (priv->pcs && priv->hw->mac->pcs_ctrl_ane)
+       if (priv->hw->pcs && priv->hw->mac->pcs_ctrl_ane)
                priv->hw->mac->pcs_ctrl_ane(priv->hw, 1, 0, 0);
 
        /*  set TX ring length */
@@ -1748,8 +1749,9 @@ static int stmmac_open(struct net_device *dev)
 
        stmmac_check_ether_addr(priv);
 
-       if (priv->pcs != STMMAC_PCS_RGMII && priv->pcs != STMMAC_PCS_TBI &&
-           priv->pcs != STMMAC_PCS_RTBI) {
+       if (priv->hw->pcs != STMMAC_PCS_RGMII &&
+           priv->hw->pcs != STMMAC_PCS_TBI &&
+           priv->hw->pcs != STMMAC_PCS_RTBI) {
                ret = stmmac_init_phy(dev);
                if (ret) {
                        pr_err("%s: Cannot attach to PHY (error: %d)\n",
@@ -2811,7 +2813,7 @@ static irqreturn_t stmmac_interrupt(int irq, void *dev_id)
                }
 
                /* PCS link status */
-               if (priv->pcs) {
+               if (priv->hw->pcs) {
                        if (priv->xstats.pcs_link)
                                netif_carrier_on(dev);
                        else
@@ -3138,6 +3140,7 @@ static int stmmac_hw_init(struct stmmac_priv *priv)
                 */
                priv->plat->enh_desc = priv->dma_cap.enh_desc;
                priv->plat->pmt = priv->dma_cap.pmt_remote_wake_up;
+               priv->hw->pmt = priv->plat->pmt;
 
                /* TXCOE doesn't work in thresh DMA mode */
                if (priv->plat->force_thresh_dma_mode)
@@ -3333,8 +3336,9 @@ int stmmac_dvr_probe(struct device *device,
 
        stmmac_check_pcs_mode(priv);
 
-       if (priv->pcs != STMMAC_PCS_RGMII && priv->pcs != STMMAC_PCS_TBI &&
-           priv->pcs != STMMAC_PCS_RTBI) {
+       if (priv->hw->pcs != STMMAC_PCS_RGMII  &&
+           priv->hw->pcs != STMMAC_PCS_TBI &&
+           priv->hw->pcs != STMMAC_PCS_RTBI) {
                /* MDIO bus Registration */
                ret = stmmac_mdio_register(ndev);
                if (ret < 0) {
@@ -3384,8 +3388,9 @@ int stmmac_dvr_remove(struct device *dev)
                reset_control_assert(priv->stmmac_rst);
        clk_disable_unprepare(priv->pclk);
        clk_disable_unprepare(priv->stmmac_clk);
-       if (priv->pcs != STMMAC_PCS_RGMII && priv->pcs != STMMAC_PCS_TBI &&
-           priv->pcs != STMMAC_PCS_RTBI)
+       if (priv->hw->pcs != STMMAC_PCS_RGMII &&
+           priv->hw->pcs != STMMAC_PCS_TBI &&
+           priv->hw->pcs != STMMAC_PCS_RTBI)
                stmmac_mdio_unregister(ndev);
        free_netdev(ndev);