Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drivers: net: stmmac: rework core ISR to better manage PCS and PMT

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>

authored by

Giuseppe CAVALLARO and committed by
David S. Miller
3fe5cadb 70523e63

+79 -35
+2
drivers/net/ethernet/stmicro/stmmac/common.h
··· 529 529 int unicast_filter_entries; 530 530 int mcast_bits_log2; 531 531 unsigned int rx_csum; 532 + unsigned int pcs; 533 + unsigned int pmt; 532 534 }; 533 535 534 536 struct mac_device_info *dwmac1000_setup(void __iomem *ioaddr, int mcbins,
+20 -10
drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
··· 38 38 #define GMAC_WAKEUP_FILTER 0x00000028 /* Wake-up Frame Filter */ 39 39 40 40 #define GMAC_INT_STATUS 0x00000038 /* interrupt status register */ 41 - enum dwmac1000_irq_status { 42 - lpiis_irq = 0x400, 43 - time_stamp_irq = 0x0200, 44 - mmc_rx_csum_offload_irq = 0x0080, 45 - mmc_tx_irq = 0x0040, 46 - mmc_rx_irq = 0x0020, 47 - mmc_irq = 0x0010, 48 - pmt_irq = 0x0008, 49 - }; 50 - #define GMAC_INT_MASK 0x0000003c /* interrupt mask register */ 41 + #define GMAC_INT_STATUS_PMT BIT(3) 42 + #define GMAC_INT_STATUS_MMCIS BIT(4) 43 + #define GMAC_INT_STATUS_MMCRIS BIT(5) 44 + #define GMAC_INT_STATUS_MMCTIS BIT(6) 45 + #define GMAC_INT_STATUS_MMCCSUM BIT(7) 46 + #define GMAC_INT_STATUS_TSTAMP BIT(9) 47 + #define GMAC_INT_STATUS_LPIIS BIT(10) 48 + 49 + /* interrupt mask register */ 50 + #define GMAC_INT_MASK 0x0000003c 51 + #define GMAC_INT_DISABLE_RGMII BIT(0) 52 + #define GMAC_INT_DISABLE_PCSLINK BIT(1) 53 + #define GMAC_INT_DISABLE_PCSAN BIT(2) 54 + #define GMAC_INT_DISABLE_PMT BIT(3) 55 + #define GMAC_INT_DISABLE_TIMESTAMP BIT(9) 56 + #define GMAC_INT_DISABLE_PCS (GMAC_INT_DISABLE_RGMII | \ 57 + GMAC_INT_DISABLE_PCSLINK | \ 58 + GMAC_INT_DISABLE_PCSAN) 59 + #define GMAC_INT_DEFAULT_MASK (GMAC_INT_DISABLE_TIMESTAMP | \ 60 + GMAC_INT_DISABLE_PCS) 51 61 52 62 /* PMT Control and Status */ 53 63 #define GMAC_PMT 0x0000002c
+17 -7
drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
··· 37 37 { 38 38 void __iomem *ioaddr = hw->pcsr; 39 39 u32 value = readl(ioaddr + GMAC_CONTROL); 40 + 41 + /* Configure GMAC core */ 40 42 value |= GMAC_CORE_INIT; 43 + 41 44 if (mtu > 1500) 42 45 value |= GMAC_CONTROL_2K; 43 46 if (mtu > 2000) ··· 49 46 writel(value, ioaddr + GMAC_CONTROL); 50 47 51 48 /* Mask GMAC interrupts */ 52 - writel(0x207, ioaddr + GMAC_INT_MASK); 49 + value = GMAC_INT_DEFAULT_MASK; 50 + 51 + if (hw->pmt) 52 + value &= ~GMAC_INT_DISABLE_PMT; 53 + if (hw->pcs) 54 + value &= ~GMAC_INT_DISABLE_PCS; 55 + 56 + writel(value, ioaddr + GMAC_INT_MASK); 53 57 54 58 #ifdef STMMAC_VLAN_TAG_USED 55 59 /* Tag detection without filtering */ ··· 293 283 int ret = 0; 294 284 295 285 /* Not used events (e.g. MMC interrupts) are not handled. */ 296 - if ((intr_status & mmc_tx_irq)) 286 + if ((intr_status & GMAC_INT_STATUS_MMCTIS)) 297 287 x->mmc_tx_irq_n++; 298 - if (unlikely(intr_status & mmc_rx_irq)) 288 + if (unlikely(intr_status & GMAC_INT_STATUS_MMCRIS)) 299 289 x->mmc_rx_irq_n++; 300 - if (unlikely(intr_status & mmc_rx_csum_offload_irq)) 290 + if (unlikely(intr_status & GMAC_INT_STATUS_MMCCSUM)) 301 291 x->mmc_rx_csum_offload_irq_n++; 302 - if (unlikely(intr_status & pmt_irq)) { 292 + if (unlikely(intr_status & GMAC_INT_DISABLE_PMT)) { 303 293 /* clear the PMT bits 5 and 6 by reading the PMT status reg */ 304 294 readl(ioaddr + GMAC_PMT); 305 295 x->irq_receive_pmt_irq_n++; 306 296 } 307 297 308 - /* MAC trx/rx EEE LPI entry/exit interrupts */ 309 - if (intr_status & lpiis_irq) { 298 + /* MAC tx/rx EEE LPI entry/exit interrupts */ 299 + if (intr_status & GMAC_INT_STATUS_LPIIS) { 310 300 /* Clean LPI interrupt by reading the Reg 12 */ 311 301 ret = readl(ioaddr + LPI_CTRL_STATUS); 312 302
+9
drivers/net/ethernet/stmicro/stmmac/dwmac4.h
··· 52 52 #define GMAC_TX_FLOW_CTRL_PT_SHIFT 16 53 53 54 54 /* MAC Interrupt bitmap*/ 55 + #define GMAC_INT_RGSMIIS BIT(0) 56 + #define GMAC_INT_PCS_LINK BIT(1) 57 + #define GMAC_INT_PCS_ANE BIT(2) 58 + #define GMAC_INT_PCS_PHYIS BIT(3) 55 59 #define GMAC_INT_PMT_EN BIT(4) 56 60 #define GMAC_INT_LPI_EN BIT(5) 61 + 62 + #define GMAC_PCS_IRQ_DEFAULT (GMAC_INT_RGSMIIS | GMAC_INT_PCS_LINK | \ 63 + GMAC_INT_PCS_ANE) 64 + 65 + #define GMAC_INT_DEFAULT_MASK GMAC_INT_PMT_EN 57 66 58 67 enum dwmac4_irq_status { 59 68 time_stamp_irq = 0x00001000,
+7 -1
drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
··· 35 35 writel(value, ioaddr + GMAC_CONFIG); 36 36 37 37 /* Mask GMAC interrupts */ 38 - writel(GMAC_INT_PMT_EN, ioaddr + GMAC_INT_EN); 38 + value = GMAC_INT_DEFAULT_MASK; 39 + if (hw->pmt) 40 + value |= GMAC_INT_PMT_EN; 41 + if (hw->pcs) 42 + value |= GMAC_PCS_IRQ_DEFAULT; 43 + 44 + writel(value, ioaddr + GMAC_INT_EN); 39 45 } 40 46 41 47 static void dwmac4_dump_regs(struct mac_device_info *hw)
-1
drivers/net/ethernet/stmicro/stmmac/stmmac.h
··· 117 117 int eee_enabled; 118 118 int eee_active; 119 119 int tx_lpi_timer; 120 - int pcs; 121 120 unsigned int mode; 122 121 int extend_desc; 123 122 struct ptp_clock *ptp_clock;
+7 -4
drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
··· 276 276 struct phy_device *phy = priv->phydev; 277 277 int rc; 278 278 279 - if ((priv->pcs & STMMAC_PCS_RGMII) || (priv->pcs & STMMAC_PCS_SGMII)) { 279 + if (priv->hw->pcs & STMMAC_PCS_RGMII || 280 + priv->hw->pcs & STMMAC_PCS_SGMII) { 280 281 struct rgmii_adv adv; 281 282 282 283 if (!priv->xstats.pcs_link) { ··· 362 361 struct phy_device *phy = priv->phydev; 363 362 int rc; 364 363 365 - if ((priv->pcs & STMMAC_PCS_RGMII) || (priv->pcs & STMMAC_PCS_SGMII)) { 364 + if (priv->hw->pcs & STMMAC_PCS_RGMII || 365 + priv->hw->pcs & STMMAC_PCS_SGMII) { 366 366 u32 mask = ADVERTISED_Autoneg | ADVERTISED_Pause; 367 367 368 368 /* Only support ANE */ ··· 459 457 pause->rx_pause = 0; 460 458 pause->tx_pause = 0; 461 459 462 - if (priv->pcs && priv->hw->mac->pcs_get_adv_lp) { 460 + if (priv->hw->pcs && priv->hw->mac->pcs_get_adv_lp) { 463 461 struct rgmii_adv adv_lp; 464 462 465 463 pause->autoneg = 1; ··· 489 487 struct phy_device *phy = priv->phydev; 490 488 int new_pause = FLOW_OFF; 491 489 492 - if (priv->pcs && priv->hw->mac->pcs_get_adv_lp) { 490 + if (priv->hw->pcs && priv->hw->mac->pcs_get_adv_lp) { 493 491 struct rgmii_adv adv_lp; 494 492 495 493 pause->autoneg = 1; ··· 509 507 510 508 priv->flow_ctrl = new_pause; 511 509 phy->autoneg = pause->autoneg; 510 + 512 511 if (phy->autoneg) { 513 512 if (netif_running(netdev)) 514 513 return phy_start_aneg(phy);
+17 -12
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
··· 285 285 /* Using PCS we cannot dial with the phy registers at this stage 286 286 * so we do not support extra feature like EEE. 287 287 */ 288 - if ((priv->pcs == STMMAC_PCS_RGMII) || (priv->pcs == STMMAC_PCS_TBI) || 289 - (priv->pcs == STMMAC_PCS_RTBI)) 288 + if ((priv->hw->pcs == STMMAC_PCS_RGMII) || 289 + (priv->hw->pcs == STMMAC_PCS_TBI) || 290 + (priv->hw->pcs == STMMAC_PCS_RTBI)) 290 291 goto out; 291 292 292 293 /* MAC core supports the EEE feature. */ ··· 800 799 (interface == PHY_INTERFACE_MODE_RGMII_RXID) || 801 800 (interface == PHY_INTERFACE_MODE_RGMII_TXID)) { 802 801 pr_debug("STMMAC: PCS RGMII support enable\n"); 803 - priv->pcs = STMMAC_PCS_RGMII; 802 + priv->hw->pcs = STMMAC_PCS_RGMII; 804 803 } else if (interface == PHY_INTERFACE_MODE_SGMII) { 805 804 pr_debug("STMMAC: PCS SGMII support enable\n"); 806 - priv->pcs = STMMAC_PCS_SGMII; 805 + priv->hw->pcs = STMMAC_PCS_SGMII; 807 806 } 808 807 } 809 808 } ··· 1715 1714 priv->hw->dma->rx_watchdog(priv->ioaddr, MAX_DMA_RIWT); 1716 1715 } 1717 1716 1718 - if (priv->pcs && priv->hw->mac->pcs_ctrl_ane) 1717 + if (priv->hw->pcs && priv->hw->mac->pcs_ctrl_ane) 1719 1718 priv->hw->mac->pcs_ctrl_ane(priv->hw, 1, 0, 0); 1720 1719 1721 1720 /* set TX ring length */ ··· 1749 1748 1750 1749 stmmac_check_ether_addr(priv); 1751 1750 1752 - if (priv->pcs != STMMAC_PCS_RGMII && priv->pcs != STMMAC_PCS_TBI && 1753 - priv->pcs != STMMAC_PCS_RTBI) { 1751 + if (priv->hw->pcs != STMMAC_PCS_RGMII && 1752 + priv->hw->pcs != STMMAC_PCS_TBI && 1753 + priv->hw->pcs != STMMAC_PCS_RTBI) { 1754 1754 ret = stmmac_init_phy(dev); 1755 1755 if (ret) { 1756 1756 pr_err("%s: Cannot attach to PHY (error: %d)\n", ··· 2813 2811 } 2814 2812 2815 2813 /* PCS link status */ 2816 - if (priv->pcs) { 2814 + if (priv->hw->pcs) { 2817 2815 if (priv->xstats.pcs_link) 2818 2816 netif_carrier_on(dev); 2819 2817 else ··· 3140 3138 */ 3141 3139 priv->plat->enh_desc = priv->dma_cap.enh_desc; 3142 3140 priv->plat->pmt = priv->dma_cap.pmt_remote_wake_up; 3141 + priv->hw->pmt = priv->plat->pmt; 3143 3142 3144 3143 /* TXCOE doesn't work in thresh DMA mode */ 3145 3144 if (priv->plat->force_thresh_dma_mode) ··· 3336 3333 3337 3334 stmmac_check_pcs_mode(priv); 3338 3335 3339 - if (priv->pcs != STMMAC_PCS_RGMII && priv->pcs != STMMAC_PCS_TBI && 3340 - priv->pcs != STMMAC_PCS_RTBI) { 3336 + if (priv->hw->pcs != STMMAC_PCS_RGMII && 3337 + priv->hw->pcs != STMMAC_PCS_TBI && 3338 + priv->hw->pcs != STMMAC_PCS_RTBI) { 3341 3339 /* MDIO bus Registration */ 3342 3340 ret = stmmac_mdio_register(ndev); 3343 3341 if (ret < 0) { ··· 3388 3384 reset_control_assert(priv->stmmac_rst); 3389 3385 clk_disable_unprepare(priv->pclk); 3390 3386 clk_disable_unprepare(priv->stmmac_clk); 3391 - if (priv->pcs != STMMAC_PCS_RGMII && priv->pcs != STMMAC_PCS_TBI && 3392 - priv->pcs != STMMAC_PCS_RTBI) 3387 + if (priv->hw->pcs != STMMAC_PCS_RGMII && 3388 + priv->hw->pcs != STMMAC_PCS_TBI && 3389 + priv->hw->pcs != STMMAC_PCS_RTBI) 3393 3390 stmmac_mdio_unregister(ndev); 3394 3391 free_netdev(ndev); 3395 3392