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

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'net-stmmac-pcs-support-part-2'

Russell King says:

====================
net: stmmac: pcs support part 2

This is the next part of stmmac PCS support. Not much here, other than
dealing with what remains of the interrupts, which are the PCS AN
complete and PCS Link interrupts, which are just cleared and update
accounting.

Currently, they are enabled at core init time, but if we have an
implementation that supports multiple PHY interfaces, we want to
enable only the appropriate interrupts.

I also noticed that stmmac_fpe_configure_pmac() also modifies the
interrupt mask during run time. As a pre-requisit, we need a way
to ensure that we don't have different threads modifying the
interrupt settings at the same time. So, the first patch introduces
a new function and a spinlock which must be held when manipulating
the interrupt enable/mask state.

The second patch adds the PCS bits for enabling the PCS AN and PCS
link interrupts when the PCS is in-use.
====================

Link: https://patch.msgid.link/aPn5YVeUcWo4CW3c@shell.armlinux.org.uk
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+96 -22
+5
drivers/net/ethernet/stmicro/stmmac/common.h
··· 611 611 u8 vlan_fail_q; 612 612 bool hw_vlan_en; 613 613 bool reverse_sgmii_enable; 614 + 615 + /* This spinlock protects read-modify-write of the interrupt 616 + * mask/enable registers. 617 + */ 618 + spinlock_t irq_ctrl_lock; 614 619 }; 615 620 616 621 struct stmmac_rx_routing {
+3 -4
drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
··· 38 38 #define GMAC_INT_DISABLE_PCSAN BIT(2) 39 39 #define GMAC_INT_DISABLE_PMT BIT(3) 40 40 #define GMAC_INT_DISABLE_TIMESTAMP BIT(9) 41 - #define GMAC_INT_DISABLE_PCS (GMAC_INT_DISABLE_PCSLINK | \ 42 - GMAC_INT_DISABLE_PCSAN) 43 41 #define GMAC_INT_DEFAULT_MASK (GMAC_INT_DISABLE_RGMII | \ 44 - GMAC_INT_DISABLE_TIMESTAMP | \ 45 - GMAC_INT_DISABLE_PCS) 42 + GMAC_INT_DISABLE_PCSLINK | \ 43 + GMAC_INT_DISABLE_PCSAN | \ 44 + GMAC_INT_DISABLE_TIMESTAMP) 46 45 47 46 /* PMT Control and Status */ 48 47 #define GMAC_PMT 0x0000002c
+19 -7
drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
··· 27 27 if (!priv->dma_cap.pcs) 28 28 return 0; 29 29 30 - return stmmac_integrated_pcs_init(priv, GMAC_PCS_BASE); 30 + return stmmac_integrated_pcs_init(priv, GMAC_PCS_BASE, 31 + GMAC_INT_DISABLE_PCSLINK | 32 + GMAC_INT_DISABLE_PCSAN); 31 33 } 32 34 33 35 static void dwmac1000_core_init(struct mac_device_info *hw, ··· 50 48 writel(value | GMAC_CORE_INIT, ioaddr + GMAC_CONTROL); 51 49 52 50 /* Mask GMAC interrupts */ 53 - value = GMAC_INT_DEFAULT_MASK; 54 - 55 - if (hw->pcs) 56 - value &= ~GMAC_INT_DISABLE_PCS; 57 - 58 - writel(value, ioaddr + GMAC_INT_MASK); 51 + writel(GMAC_INT_DEFAULT_MASK, ioaddr + GMAC_INT_MASK); 59 52 60 53 #ifdef STMMAC_VLAN_TAG_USED 61 54 /* Tag detection without filtering */ 62 55 writel(0x0, ioaddr + GMAC_VLAN_TAG); 63 56 #endif 57 + } 58 + 59 + static void dwmac1000_irq_modify(struct mac_device_info *hw, u32 disable, 60 + u32 enable) 61 + { 62 + void __iomem *int_mask = hw->pcsr + GMAC_INT_MASK; 63 + unsigned long flags; 64 + u32 value; 65 + 66 + spin_lock_irqsave(&hw->irq_ctrl_lock, flags); 67 + value = readl(int_mask) | disable; 68 + value &= ~enable; 69 + writel(value, int_mask); 70 + spin_unlock_irqrestore(&hw->irq_ctrl_lock, flags); 64 71 } 65 72 66 73 static int dwmac1000_rx_ipc_enable(struct mac_device_info *hw) ··· 456 445 const struct stmmac_ops dwmac1000_ops = { 457 446 .pcs_init = dwmac1000_pcs_init, 458 447 .core_init = dwmac1000_core_init, 448 + .irq_modify = dwmac1000_irq_modify, 459 449 .set_mac = stmmac_set_mac, 460 450 .rx_ipc = dwmac1000_rx_ipc_enable, 461 451 .dump_regs = dwmac1000_dump_regs,
-2
drivers/net/ethernet/stmicro/stmmac/dwmac4.h
··· 106 106 #define GMAC_INT_LPI_EN BIT(5) 107 107 #define GMAC_INT_TSIE BIT(12) 108 108 109 - #define GMAC_PCS_IRQ_DEFAULT (GMAC_INT_PCS_LINK | GMAC_INT_PCS_ANE) 110 - 111 109 #define GMAC_INT_DEFAULT_ENABLE (GMAC_INT_PMT_EN | GMAC_INT_LPI_EN | \ 112 110 GMAC_INT_TSIE) 113 111
+20 -7
drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
··· 27 27 if (!priv->dma_cap.pcs) 28 28 return 0; 29 29 30 - return stmmac_integrated_pcs_init(priv, GMAC_PCS_BASE); 30 + return stmmac_integrated_pcs_init(priv, GMAC_PCS_BASE, 31 + GMAC_INT_PCS_LINK | GMAC_INT_PCS_ANE); 31 32 } 32 33 33 34 static void dwmac4_core_init(struct mac_device_info *hw, ··· 47 46 writel((clk_rate / 1000000) - 1, ioaddr + GMAC4_MAC_ONEUS_TIC_COUNTER); 48 47 49 48 /* Enable GMAC interrupts */ 50 - value = GMAC_INT_DEFAULT_ENABLE; 51 - 52 - if (hw->pcs) 53 - value |= GMAC_PCS_IRQ_DEFAULT; 54 - 55 - writel(value, ioaddr + GMAC_INT_EN); 49 + writel(GMAC_INT_DEFAULT_ENABLE, ioaddr + GMAC_INT_EN); 56 50 57 51 if (GMAC_INT_DEFAULT_ENABLE & GMAC_INT_TSIE) 58 52 init_waitqueue_head(&priv->tstamp_busy_wait); 53 + } 54 + 55 + static void dwmac4_irq_modify(struct mac_device_info *hw, u32 disable, 56 + u32 enable) 57 + { 58 + void __iomem *int_mask = hw->pcsr + GMAC_INT_EN; 59 + unsigned long flags; 60 + u32 value; 61 + 62 + spin_lock_irqsave(&hw->irq_ctrl_lock, flags); 63 + value = readl(int_mask) & ~disable; 64 + value |= enable; 65 + writel(value, int_mask); 66 + spin_unlock_irqrestore(&hw->irq_ctrl_lock, flags); 59 67 } 60 68 61 69 static void dwmac4_update_caps(struct stmmac_priv *priv) ··· 895 885 const struct stmmac_ops dwmac4_ops = { 896 886 .pcs_init = dwmac4_pcs_init, 897 887 .core_init = dwmac4_core_init, 888 + .irq_modify = dwmac4_irq_modify, 898 889 .update_caps = dwmac4_update_caps, 899 890 .set_mac = stmmac_set_mac, 900 891 .rx_ipc = dwmac4_rx_ipc_enable, ··· 931 920 const struct stmmac_ops dwmac410_ops = { 932 921 .pcs_init = dwmac4_pcs_init, 933 922 .core_init = dwmac4_core_init, 923 + .irq_modify = dwmac4_irq_modify, 934 924 .update_caps = dwmac4_update_caps, 935 925 .set_mac = stmmac_dwmac4_set_mac, 936 926 .rx_ipc = dwmac4_rx_ipc_enable, ··· 969 957 const struct stmmac_ops dwmac510_ops = { 970 958 .pcs_init = dwmac4_pcs_init, 971 959 .core_init = dwmac4_core_init, 960 + .irq_modify = dwmac4_irq_modify, 972 961 .update_caps = dwmac4_update_caps, 973 962 .set_mac = stmmac_dwmac4_set_mac, 974 963 .rx_ipc = dwmac4_rx_ipc_enable,
+16
drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
··· 28 28 writel(XGMAC_INT_DEFAULT_EN, ioaddr + XGMAC_INT_EN); 29 29 } 30 30 31 + static void dwxgmac2_irq_modify(struct mac_device_info *hw, u32 disable, 32 + u32 enable) 33 + { 34 + void __iomem *int_mask = hw->pcsr + XGMAC_INT_EN; 35 + unsigned long flags; 36 + u32 value; 37 + 38 + spin_lock_irqsave(&hw->irq_ctrl_lock, flags); 39 + value = readl(int_mask) & ~disable; 40 + value |= enable; 41 + writel(value, int_mask); 42 + spin_unlock_irqrestore(&hw->irq_ctrl_lock, flags); 43 + } 44 + 31 45 static void dwxgmac2_update_caps(struct stmmac_priv *priv) 32 46 { 33 47 if (!priv->dma_cap.mbps_10_100) ··· 1425 1411 1426 1412 const struct stmmac_ops dwxgmac210_ops = { 1427 1413 .core_init = dwxgmac2_core_init, 1414 + .irq_modify = dwxgmac2_irq_modify, 1428 1415 .update_caps = dwxgmac2_update_caps, 1429 1416 .set_mac = dwxgmac2_set_mac, 1430 1417 .rx_ipc = dwxgmac2_rx_ipc, ··· 1481 1466 1482 1467 const struct stmmac_ops dwxlgmac2_ops = { 1483 1468 .core_init = dwxgmac2_core_init, 1469 + .irq_modify = dwxgmac2_irq_modify, 1484 1470 .set_mac = dwxgmac2_set_mac, 1485 1471 .rx_ipc = dwxgmac2_rx_ipc, 1486 1472 .rx_queue_enable = dwxlgmac2_rx_queue_enable,
+2
drivers/net/ethernet/stmicro/stmmac/hwif.c
··· 333 333 if (!mac) 334 334 return -ENOMEM; 335 335 336 + spin_lock_init(&mac->irq_ctrl_lock); 337 + 336 338 /* Fallback to generic HW */ 337 339 for (i = ARRAY_SIZE(stmmac_hw) - 1; i >= 0; i--) { 338 340 entry = &stmmac_hw[i];
+4
drivers/net/ethernet/stmicro/stmmac/hwif.h
··· 319 319 void (*core_init)(struct mac_device_info *hw, struct net_device *dev); 320 320 /* Update MAC capabilities */ 321 321 void (*update_caps)(struct stmmac_priv *priv); 322 + /* Change the interrupt enable setting. Enable takes precedence. */ 323 + void (*irq_modify)(struct mac_device_info *hw, u32 disable, u32 enable); 322 324 /* Enable the MAC RX/TX */ 323 325 void (*set_mac)(void __iomem *ioaddr, bool enable); 324 326 /* Enable and verify that the IPC module is supported */ ··· 423 421 stmmac_do_void_callback(__priv, mac, core_init, __args) 424 422 #define stmmac_mac_update_caps(__priv) \ 425 423 stmmac_do_void_callback(__priv, mac, update_caps, __priv) 424 + #define stmmac_mac_irq_modify(__priv, __args...) \ 425 + stmmac_do_void_callback(__priv, mac, irq_modify, (__priv)->hw, __args) 426 426 #define stmmac_mac_set(__priv, __args...) \ 427 427 stmmac_do_void_callback(__priv, mac, set_mac, __args) 428 428 #define stmmac_rx_ipc(__priv, __args...) \
+3
drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.c
··· 70 70 struct stmmac_priv *priv = container_of(cfg, struct stmmac_priv, fpe_cfg); 71 71 const struct stmmac_fpe_reg *reg = cfg->reg; 72 72 void __iomem *ioaddr = priv->ioaddr; 73 + unsigned long flags; 73 74 u32 value; 74 75 76 + spin_lock_irqsave(&priv->hw->irq_ctrl_lock, flags); 75 77 value = readl(ioaddr + reg->int_en_reg); 76 78 77 79 if (pmac_enable) { ··· 88 86 } 89 87 90 88 writel(value, ioaddr + reg->int_en_reg); 89 + spin_unlock_irqrestore(&priv->hw->irq_ctrl_lock, flags); 91 90 } 92 91 93 92 static void stmmac_fpe_send_mpacket(struct ethtool_mmsv *mmsv,
+21 -1
drivers/net/ethernet/stmicro/stmmac/stmmac_pcs.c
··· 2 2 #include "stmmac.h" 3 3 #include "stmmac_pcs.h" 4 4 5 + static int dwmac_integrated_pcs_enable(struct phylink_pcs *pcs) 6 + { 7 + struct stmmac_pcs *spcs = phylink_pcs_to_stmmac_pcs(pcs); 8 + 9 + stmmac_mac_irq_modify(spcs->priv, 0, spcs->int_mask); 10 + 11 + return 0; 12 + } 13 + 14 + static void dwmac_integrated_pcs_disable(struct phylink_pcs *pcs) 15 + { 16 + struct stmmac_pcs *spcs = phylink_pcs_to_stmmac_pcs(pcs); 17 + 18 + stmmac_mac_irq_modify(spcs->priv, spcs->int_mask, 0); 19 + } 20 + 5 21 static void dwmac_integrated_pcs_get_state(struct phylink_pcs *pcs, 6 22 unsigned int neg_mode, 7 23 struct phylink_link_state *state) ··· 39 23 } 40 24 41 25 static const struct phylink_pcs_ops dwmac_integrated_pcs_ops = { 26 + .pcs_enable = dwmac_integrated_pcs_enable, 27 + .pcs_disable = dwmac_integrated_pcs_disable, 42 28 .pcs_get_state = dwmac_integrated_pcs_get_state, 43 29 .pcs_config = dwmac_integrated_pcs_config, 44 30 }; 45 31 46 - int stmmac_integrated_pcs_init(struct stmmac_priv *priv, unsigned int offset) 32 + int stmmac_integrated_pcs_init(struct stmmac_priv *priv, unsigned int offset, 33 + u32 int_mask) 47 34 { 48 35 struct stmmac_pcs *spcs; 49 36 ··· 56 37 57 38 spcs->priv = priv; 58 39 spcs->base = priv->ioaddr + offset; 40 + spcs->int_mask = int_mask; 59 41 spcs->pcs.ops = &dwmac_integrated_pcs_ops; 60 42 61 43 __set_bit(PHY_INTERFACE_MODE_SGMII, spcs->pcs.supported_interfaces);
+3 -1
drivers/net/ethernet/stmicro/stmmac/stmmac_pcs.h
··· 52 52 struct stmmac_pcs { 53 53 struct stmmac_priv *priv; 54 54 void __iomem *base; 55 + u32 int_mask; 55 56 struct phylink_pcs pcs; 56 57 }; 57 58 ··· 62 61 return container_of(pcs, struct stmmac_pcs, pcs); 63 62 } 64 63 65 - int stmmac_integrated_pcs_init(struct stmmac_priv *priv, unsigned int offset); 64 + int stmmac_integrated_pcs_init(struct stmmac_priv *priv, unsigned int offset, 65 + u32 int_mask); 66 66 67 67 /** 68 68 * dwmac_pcs_isr - TBI, RTBI, or SGMII PHY ISR