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-phylink-pcs-conversion'

Russell King says:

====================
net: stmmac: phylink PCS conversion

This series is radical - it takes the brave step of ripping out much of
the existing PCS support code and throwing it all away.

I have discussed the introduction of the STMMAC_FLAG_HAS_INTEGRATED_PCS
flag with Bartosz Golaszewski, and the conclusion I came to is that
this is to workaround the breakage that I've been going on about
concerning the phylink conversion for the last five or six years.

The problem is that the stmmac PCS code manipulates the netif carrier
state, which confuses phylink.

There is a way of testing this out on the Jetson Xavier NX platform as
the "PCS" code paths can be exercised while in RGMII mode - because
RGMII also has in-band status and the status register is shared with
SGMII. Testing this out confirms my long held theory: the interrupt
handler manipulates the netif carrier state before phylink gets a
look-in, which means that the mac_link_up() and mac_link_down() methods
are never called, resulting in the device being non-functional.

Moreover, on dwmac4 cores, ethtool reports incorrect information -
despite having a full-duplex link, ethtool reports that it is
half-dupex.

Thus, this code is completely broken - anyone using it will not have
a functional platform, and thus it doesn't deserve to live any longer,
especially as it's a thorn in phylink.

Rip all this out, leaving just the bare bones initialisation in place.

However, this is not the last of what's broken. We have this hw->ps
integer which is really not descriptive, and the DT property from
which it comes from does little to help understand what's going on.
Putting all the clues together:

- early configuration of the GMAC configuration register for the
speed.
- setting the SGMII rate adapter layer to take its speed from the
GMAC configuration register.

Lastly, setting the transmit enable (TE) bit, which is a typo that puts
the nail in the coffin of this code. It should be the transmit
configuration (TC) bit. Given that when the link comes up, phylink
will call mac_link_up() which will overwrite the speed in the GMAC
configuration register, the only part of this that is functional is
changing where the SGMII rate adapter layer gets its speed from,
which is a boolean.

From what I've found so far, everyone who sets the snps,ps-speed
property which configures this mode also configures a fixed link,
so the pre-configuration is unnecessary - the link will come up
anyway.

So, this series rips that out the preconfiguration as well, and
replaces hw->ps with a boolean hw->reverse_sgmii_enable flag.

We then move the sole PCS configuration into a phylink_pcs instance,
which configures the PCS control register in the same way as is done
during the probe function.

Thus, we end up with much easier and simpler conversion to phylink PCS
than previous attempts.

Even so, this still results in inband mode always being enabled at
the moment in the new .pcs_config() method to reflect what the probe
function was doing. The next stage will be to change that to allow
phylink to correctly configure the PCS. This needs fixing to allow
platform glue maintainers who are currently blocked to progress.

Please note, however, that this has not been tested with any SGMII
platform.

I've tried to get as many people into the Cc list with get_maintainers,
I hope that's sufficient to get enough eyeballs on this.

Changes since RFC:
- new patch (7) to remove RGMII "pcs" mode
- new patch (8) to move reverse "pcs" mode to stmmac_check_pcs_mode()
- new patch (9) to simplify the code moved in the previous patch
- new patch (10) to rename the confusing hw->ps to something more
understandable.
- new patch (11) to shut up inappropriate complaints about
"snps,ps-speed" being invalid.
- new patch (13) to add a MAC .pcs_init method, which will only be
called when core has PCS present.
- modify patch 14 to use this new pcs_init method.

Despite getting a couple of responses to the RFC series posted in
September, I have had nothing testing this on hardware. I have tested
this on the Jetson Xavier NX, which included trial runs with enabling
the RGMII "pcs" mode, hence the new patches that rip out this mode. I
have come to the conclusion that the only way to get stmmac changes
tested is to get them merged into net-next, thereby forcing people to
have to run with them... and we'll deal with any fallout later.
====================

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

+149 -265
+1 -1
drivers/net/ethernet/stmicro/stmmac/Makefile
··· 7 7 dwmac4_dma.o dwmac4_lib.o dwmac4_core.o dwmac5.o hwif.o \ 8 8 stmmac_tc.o dwxgmac2_core.o dwxgmac2_dma.o dwxgmac2_descs.o \ 9 9 stmmac_xdp.o stmmac_est.o stmmac_fpe.o stmmac_vlan.o \ 10 - $(stmmac-y) 10 + stmmac_pcs.o $(stmmac-y) 11 11 12 12 stmmac-$(CONFIG_STMMAC_SELFTESTS) += stmmac_selftests.o 13 13
+1 -5
drivers/net/ethernet/stmicro/stmmac/common.h
··· 192 192 unsigned long irq_pcs_ane_n; 193 193 unsigned long irq_pcs_link_n; 194 194 unsigned long irq_rgmii_n; 195 - unsigned long pcs_link; 196 - unsigned long pcs_duplex; 197 - unsigned long pcs_speed; 198 195 /* debug register */ 199 196 unsigned long mtl_tx_status_fifo_full; 200 197 unsigned long mtl_tx_fifo_not_empty; ··· 270 273 #define FLOW_AUTO (FLOW_TX | FLOW_RX) 271 274 272 275 /* PCS defines */ 273 - #define STMMAC_PCS_RGMII (1 << 0) 274 276 #define STMMAC_PCS_SGMII (1 << 1) 275 277 276 278 #define SF_DMA_MODE 1 /* DMA STORE-AND-FORWARD Operation Mode */ ··· 599 603 unsigned int mcast_bits_log2; 600 604 unsigned int rx_csum; 601 605 unsigned int pcs; 602 - unsigned int ps; 603 606 unsigned int xlgmac; 604 607 unsigned int num_vlan; 605 608 u32 vlan_filter[32]; 606 609 bool vlan_fail_q_en; 607 610 u8 vlan_fail_q; 608 611 bool hw_vlan_en; 612 + bool reverse_sgmii_enable; 609 613 }; 610 614 611 615 struct stmmac_rx_routing {
+1 -5
drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
··· 96 96 bool rgmii_config_loopback_en; 97 97 bool has_emac_ge_3; 98 98 const char *link_clk_name; 99 - bool has_integrated_pcs; 100 99 u32 dma_addr_width; 101 100 struct dwmac4_addrs dwmac4_addrs; 102 101 bool needs_sgmii_loopback; ··· 281 282 .rgmii_config_loopback_en = false, 282 283 .has_emac_ge_3 = true, 283 284 .link_clk_name = "phyaux", 284 - .has_integrated_pcs = true, 285 285 .needs_sgmii_loopback = true, 286 286 .dma_addr_width = 36, 287 287 .dwmac4_addrs = { ··· 622 624 623 625 static void ethqos_pcs_set_inband(struct stmmac_priv *priv, bool enable) 624 626 { 625 - stmmac_pcs_ctrl_ane(priv, enable, 0, 0); 627 + stmmac_pcs_ctrl_ane(priv, enable, 0); 626 628 } 627 629 628 630 /* On interface toggle MAC registers gets reset. ··· 854 856 plat_dat->flags |= STMMAC_FLAG_TSO_EN; 855 857 if (of_device_is_compatible(np, "qcom,qcs404-ethqos")) 856 858 plat_dat->flags |= STMMAC_FLAG_RX_CLK_RUNS_IN_LPI; 857 - if (data->has_integrated_pcs) 858 - plat_dat->flags |= STMMAC_FLAG_HAS_INTEGRATED_PCS; 859 859 if (data->dma_addr_width) 860 860 plat_dat->host_dma_width = data->dma_addr_width; 861 861
+3 -3
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_RGMII | \ 42 - GMAC_INT_DISABLE_PCSLINK | \ 41 + #define GMAC_INT_DISABLE_PCS (GMAC_INT_DISABLE_PCSLINK | \ 43 42 GMAC_INT_DISABLE_PCSAN) 44 - #define GMAC_INT_DEFAULT_MASK (GMAC_INT_DISABLE_TIMESTAMP | \ 43 + #define GMAC_INT_DEFAULT_MASK (GMAC_INT_DISABLE_RGMII | \ 44 + GMAC_INT_DISABLE_TIMESTAMP | \ 45 45 GMAC_INT_DISABLE_PCS) 46 46 47 47 /* PMT Control and Status */
+14 -58
drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
··· 22 22 #include "stmmac_ptp.h" 23 23 #include "dwmac1000.h" 24 24 25 + static int dwmac1000_pcs_init(struct stmmac_priv *priv) 26 + { 27 + if (!priv->dma_cap.pcs) 28 + return 0; 29 + 30 + return stmmac_integrated_pcs_init(priv, GMAC_PCS_BASE); 31 + } 32 + 25 33 static void dwmac1000_core_init(struct mac_device_info *hw, 26 34 struct net_device *dev) 27 35 { 28 36 void __iomem *ioaddr = hw->pcsr; 29 - u32 value = readl(ioaddr + GMAC_CONTROL); 30 37 int mtu = dev->mtu; 38 + u32 value; 31 39 32 40 /* Configure GMAC core */ 33 - value |= GMAC_CORE_INIT; 41 + value = readl(ioaddr + GMAC_CONTROL); 34 42 35 43 if (mtu > 1500) 36 44 value |= GMAC_CONTROL_2K; 37 45 if (mtu > 2000) 38 46 value |= GMAC_CONTROL_JE; 39 47 40 - if (hw->ps) { 41 - value |= GMAC_CONTROL_TE; 42 - 43 - value &= ~hw->link.speed_mask; 44 - switch (hw->ps) { 45 - case SPEED_1000: 46 - value |= hw->link.speed1000; 47 - break; 48 - case SPEED_100: 49 - value |= hw->link.speed100; 50 - break; 51 - case SPEED_10: 52 - value |= hw->link.speed10; 53 - break; 54 - } 55 - } 56 - 57 - writel(value, ioaddr + GMAC_CONTROL); 48 + writel(value | GMAC_CORE_INIT, ioaddr + GMAC_CONTROL); 58 49 59 50 /* Mask GMAC interrupts */ 60 51 value = GMAC_INT_DEFAULT_MASK; ··· 254 263 writel(pmt, ioaddr + GMAC_PMT); 255 264 } 256 265 257 - /* RGMII or SMII interface */ 258 - static void dwmac1000_rgsmii(void __iomem *ioaddr, struct stmmac_extra_stats *x) 259 - { 260 - u32 status; 261 - 262 - status = readl(ioaddr + GMAC_RGSMIIIS); 263 - x->irq_rgmii_n++; 264 - 265 - /* Check the link status */ 266 - if (status & GMAC_RGSMIIIS_LNKSTS) { 267 - int speed_value; 268 - 269 - x->pcs_link = 1; 270 - 271 - speed_value = ((status & GMAC_RGSMIIIS_SPEED) >> 272 - GMAC_RGSMIIIS_SPEED_SHIFT); 273 - if (speed_value == GMAC_RGSMIIIS_SPEED_125) 274 - x->pcs_speed = SPEED_1000; 275 - else if (speed_value == GMAC_RGSMIIIS_SPEED_25) 276 - x->pcs_speed = SPEED_100; 277 - else 278 - x->pcs_speed = SPEED_10; 279 - 280 - x->pcs_duplex = (status & GMAC_RGSMIIIS_LNKMOD_MASK); 281 - 282 - pr_info("Link is Up - %d/%s\n", (int)x->pcs_speed, 283 - x->pcs_duplex ? "Full" : "Half"); 284 - } else { 285 - x->pcs_link = 0; 286 - pr_info("Link is Down\n"); 287 - } 288 - } 289 - 290 266 static int dwmac1000_irq_status(struct mac_device_info *hw, 291 267 struct stmmac_extra_stats *x) 292 268 { ··· 294 336 } 295 337 296 338 dwmac_pcs_isr(ioaddr, GMAC_PCS_BASE, intr_status, x); 297 - 298 - if (intr_status & PCS_RGSMIIIS_IRQ) 299 - dwmac1000_rgsmii(ioaddr, x); 300 339 301 340 return ret; 302 341 } ··· 349 394 } 350 395 351 396 static void dwmac1000_ctrl_ane(struct stmmac_priv *priv, bool ane, 352 - bool srgmi_ral, bool loopback) 397 + bool srgmi_ral) 353 398 { 354 - dwmac_ctrl_ane(priv->ioaddr, GMAC_PCS_BASE, ane, srgmi_ral, loopback); 399 + dwmac_ctrl_ane(priv->ioaddr, GMAC_PCS_BASE, ane, srgmi_ral); 355 400 } 356 401 357 402 static void dwmac1000_debug(struct stmmac_priv *priv, void __iomem *ioaddr, ··· 443 488 } 444 489 445 490 const struct stmmac_ops dwmac1000_ops = { 491 + .pcs_init = dwmac1000_pcs_init, 446 492 .core_init = dwmac1000_core_init, 447 493 .set_mac = stmmac_set_mac, 448 494 .rx_ipc = dwmac1000_rx_ipc_enable,
+1 -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_RGSMIIS | GMAC_INT_PCS_LINK | \ 110 - GMAC_INT_PCS_ANE) 109 + #define GMAC_PCS_IRQ_DEFAULT (GMAC_INT_PCS_LINK | GMAC_INT_PCS_ANE) 111 110 112 111 #define GMAC_INT_DEFAULT_ENABLE (GMAC_INT_PMT_EN | GMAC_INT_LPI_EN | \ 113 112 GMAC_INT_TSIE)
+16 -59
drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
··· 22 22 #include "dwmac4.h" 23 23 #include "dwmac5.h" 24 24 25 + static int dwmac4_pcs_init(struct stmmac_priv *priv) 26 + { 27 + if (!priv->dma_cap.pcs) 28 + return 0; 29 + 30 + return stmmac_integrated_pcs_init(priv, GMAC_PCS_BASE); 31 + } 32 + 25 33 static void dwmac4_core_init(struct mac_device_info *hw, 26 34 struct net_device *dev) 27 35 { 28 36 struct stmmac_priv *priv = netdev_priv(dev); 29 37 void __iomem *ioaddr = hw->pcsr; 30 - u32 value = readl(ioaddr + GMAC_CONFIG); 31 38 unsigned long clk_rate; 39 + u32 value; 32 40 33 - value |= GMAC_CORE_INIT; 34 - 35 - if (hw->ps) { 36 - value |= GMAC_CONFIG_TE; 37 - 38 - value &= hw->link.speed_mask; 39 - switch (hw->ps) { 40 - case SPEED_1000: 41 - value |= hw->link.speed1000; 42 - break; 43 - case SPEED_100: 44 - value |= hw->link.speed100; 45 - break; 46 - case SPEED_10: 47 - value |= hw->link.speed10; 48 - break; 49 - } 50 - } 51 - 52 - writel(value, ioaddr + GMAC_CONFIG); 41 + value = readl(ioaddr + GMAC_CONFIG); 42 + writel(value | GMAC_CORE_INIT, ioaddr + GMAC_CONFIG); 53 43 54 44 /* Configure LPI 1us counter to number of CSR clock ticks in 1us - 1 */ 55 45 clk_rate = clk_get_rate(priv->plat->stmmac_clk); ··· 573 583 } 574 584 } 575 585 576 - static void dwmac4_ctrl_ane(struct stmmac_priv *priv, bool ane, bool srgmi_ral, 577 - bool loopback) 586 + static void dwmac4_ctrl_ane(struct stmmac_priv *priv, bool ane, bool srgmi_ral) 578 587 { 579 - dwmac_ctrl_ane(priv->ioaddr, GMAC_PCS_BASE, ane, srgmi_ral, loopback); 580 - } 581 - 582 - /* RGMII or SMII interface */ 583 - static void dwmac4_phystatus(void __iomem *ioaddr, struct stmmac_extra_stats *x) 584 - { 585 - u32 status; 586 - 587 - status = readl(ioaddr + GMAC_PHYIF_CONTROL_STATUS); 588 - x->irq_rgmii_n++; 589 - 590 - /* Check the link status */ 591 - if (status & GMAC_PHYIF_CTRLSTATUS_LNKSTS) { 592 - int speed_value; 593 - 594 - x->pcs_link = 1; 595 - 596 - speed_value = ((status & GMAC_PHYIF_CTRLSTATUS_SPEED) >> 597 - GMAC_PHYIF_CTRLSTATUS_SPEED_SHIFT); 598 - if (speed_value == GMAC_PHYIF_CTRLSTATUS_SPEED_125) 599 - x->pcs_speed = SPEED_1000; 600 - else if (speed_value == GMAC_PHYIF_CTRLSTATUS_SPEED_25) 601 - x->pcs_speed = SPEED_100; 602 - else 603 - x->pcs_speed = SPEED_10; 604 - 605 - x->pcs_duplex = (status & GMAC_PHYIF_CTRLSTATUS_LNKMOD); 606 - 607 - pr_info("Link is Up - %d/%s\n", (int)x->pcs_speed, 608 - x->pcs_duplex ? "Full" : "Half"); 609 - } else { 610 - x->pcs_link = 0; 611 - pr_info("Link is Down\n"); 612 - } 588 + dwmac_ctrl_ane(priv->ioaddr, GMAC_PCS_BASE, ane, srgmi_ral); 613 589 } 614 590 615 591 static int dwmac4_irq_mtl_status(struct stmmac_priv *priv, ··· 649 693 } 650 694 651 695 dwmac_pcs_isr(ioaddr, GMAC_PCS_BASE, intr_status, x); 652 - if (intr_status & PCS_RGSMIIIS_IRQ) 653 - dwmac4_phystatus(ioaddr, x); 654 696 655 697 return ret; 656 698 } ··· 883 929 } 884 930 885 931 const struct stmmac_ops dwmac4_ops = { 932 + .pcs_init = dwmac4_pcs_init, 886 933 .core_init = dwmac4_core_init, 887 934 .update_caps = dwmac4_update_caps, 888 935 .set_mac = stmmac_set_mac, ··· 918 963 }; 919 964 920 965 const struct stmmac_ops dwmac410_ops = { 966 + .pcs_init = dwmac4_pcs_init, 921 967 .core_init = dwmac4_core_init, 922 968 .update_caps = dwmac4_update_caps, 923 969 .set_mac = stmmac_dwmac4_set_mac, ··· 955 999 }; 956 1000 957 1001 const struct stmmac_ops dwmac510_ops = { 1002 + .pcs_init = dwmac4_pcs_init, 958 1003 .core_init = dwmac4_core_init, 959 1004 .update_caps = dwmac4_update_caps, 960 1005 .set_mac = stmmac_dwmac4_set_mac,
+2 -23
drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
··· 23 23 tx = readl(ioaddr + XGMAC_TX_CONFIG); 24 24 rx = readl(ioaddr + XGMAC_RX_CONFIG); 25 25 26 - tx |= XGMAC_CORE_INIT_TX; 27 - rx |= XGMAC_CORE_INIT_RX; 28 - 29 - if (hw->ps) { 30 - tx |= XGMAC_CONFIG_TE; 31 - tx &= ~hw->link.speed_mask; 32 - 33 - switch (hw->ps) { 34 - case SPEED_10000: 35 - tx |= hw->link.xgmii.speed10000; 36 - break; 37 - case SPEED_2500: 38 - tx |= hw->link.speed2500; 39 - break; 40 - case SPEED_1000: 41 - default: 42 - tx |= hw->link.speed1000; 43 - break; 44 - } 45 - } 46 - 47 - writel(tx, ioaddr + XGMAC_TX_CONFIG); 48 - writel(rx, ioaddr + XGMAC_RX_CONFIG); 26 + writel(tx | XGMAC_CORE_INIT_TX, ioaddr + XGMAC_TX_CONFIG); 27 + writel(rx | XGMAC_CORE_INIT_RX, ioaddr + XGMAC_RX_CONFIG); 49 28 writel(XGMAC_INT_DEFAULT_EN, ioaddr + XGMAC_INT_EN); 50 29 } 51 30
+6 -2
drivers/net/ethernet/stmicro/stmmac/hwif.h
··· 313 313 314 314 /* Helpers to program the MAC core */ 315 315 struct stmmac_ops { 316 + /* Initialise any PCS instances */ 317 + int (*pcs_init)(struct stmmac_priv *priv); 316 318 /* MAC core initialization */ 317 319 void (*core_init)(struct mac_device_info *hw, struct net_device *dev); 318 320 /* Update MAC capabilities */ ··· 376 374 struct stmmac_extra_stats *x, u32 rx_queues, 377 375 u32 tx_queues); 378 376 /* PCS calls */ 379 - void (*pcs_ctrl_ane)(struct stmmac_priv *priv, bool ane, bool srgmi_ral, 380 - bool loopback); 377 + void (*pcs_ctrl_ane)(struct stmmac_priv *priv, bool ane, 378 + bool srgmi_ral); 381 379 /* Safety Features */ 382 380 int (*safety_feat_config)(void __iomem *ioaddr, unsigned int asp, 383 381 struct stmmac_safety_feature_cfg *safety_cfg); ··· 415 413 u32 pclass); 416 414 }; 417 415 416 + #define stmmac_mac_pcs_init(__priv) \ 417 + stmmac_do_callback(__priv, mac, pcs_init, __priv) 418 418 #define stmmac_core_init(__priv, __args...) \ 419 419 stmmac_do_void_callback(__priv, mac, core_init, __args) 420 420 #define stmmac_mac_update_caps(__priv) \
+4
drivers/net/ethernet/stmicro/stmmac/stmmac.h
··· 25 25 #include <net/xdp.h> 26 26 #include <uapi/linux/bpf.h> 27 27 28 + struct stmmac_pcs; 29 + 28 30 struct stmmac_resources { 29 31 void __iomem *addr; 30 32 u8 mac[ETH_ALEN]; ··· 274 272 275 273 unsigned int pause_time; 276 274 struct mii_bus *mii; 275 + 276 + struct stmmac_pcs *integrated_pcs; 277 277 278 278 struct phylink_config phylink_config; 279 279 struct phylink *phylink;
+2 -66
drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
··· 322 322 { 323 323 struct stmmac_priv *priv = netdev_priv(dev); 324 324 325 - if (!(priv->plat->flags & STMMAC_FLAG_HAS_INTEGRATED_PCS) && 326 - (priv->hw->pcs & STMMAC_PCS_RGMII || 327 - priv->hw->pcs & STMMAC_PCS_SGMII)) { 328 - u32 supported, advertising, lp_advertising; 329 - 330 - if (!priv->xstats.pcs_link) { 331 - cmd->base.speed = SPEED_UNKNOWN; 332 - cmd->base.duplex = DUPLEX_UNKNOWN; 333 - return 0; 334 - } 335 - cmd->base.duplex = priv->xstats.pcs_duplex; 336 - 337 - cmd->base.speed = priv->xstats.pcs_speed; 338 - 339 - /* Encoding of PSE bits is defined in 802.3z, 37.2.1.4 */ 340 - 341 - ethtool_convert_link_mode_to_legacy_u32( 342 - &supported, cmd->link_modes.supported); 343 - ethtool_convert_link_mode_to_legacy_u32( 344 - &advertising, cmd->link_modes.advertising); 345 - ethtool_convert_link_mode_to_legacy_u32( 346 - &lp_advertising, cmd->link_modes.lp_advertising); 347 - 348 - /* Reg49[3] always set because ANE is always supported */ 349 - cmd->base.autoneg = ADVERTISED_Autoneg; 350 - supported |= SUPPORTED_Autoneg; 351 - advertising |= ADVERTISED_Autoneg; 352 - lp_advertising |= ADVERTISED_Autoneg; 353 - 354 - cmd->base.port = PORT_OTHER; 355 - 356 - ethtool_convert_legacy_u32_to_link_mode( 357 - cmd->link_modes.supported, supported); 358 - ethtool_convert_legacy_u32_to_link_mode( 359 - cmd->link_modes.advertising, advertising); 360 - ethtool_convert_legacy_u32_to_link_mode( 361 - cmd->link_modes.lp_advertising, lp_advertising); 362 - 363 - return 0; 364 - } 365 - 366 325 return phylink_ethtool_ksettings_get(priv->phylink, cmd); 367 326 } 368 327 ··· 330 371 const struct ethtool_link_ksettings *cmd) 331 372 { 332 373 struct stmmac_priv *priv = netdev_priv(dev); 333 - 334 - if (!(priv->plat->flags & STMMAC_FLAG_HAS_INTEGRATED_PCS) && 335 - (priv->hw->pcs & STMMAC_PCS_RGMII || 336 - priv->hw->pcs & STMMAC_PCS_SGMII)) { 337 - /* Only support ANE */ 338 - if (cmd->base.autoneg != AUTONEG_ENABLE) 339 - return -EINVAL; 340 - 341 - mutex_lock(&priv->lock); 342 - stmmac_pcs_ctrl_ane(priv, 1, priv->hw->ps, 0); 343 - mutex_unlock(&priv->lock); 344 - 345 - return 0; 346 - } 347 374 348 375 return phylink_ethtool_ksettings_set(priv->phylink, cmd); 349 376 } ··· 424 479 { 425 480 struct stmmac_priv *priv = netdev_priv(netdev); 426 481 427 - if (priv->hw->pcs) { 428 - pause->autoneg = 1; 429 - } else { 430 - phylink_ethtool_get_pauseparam(priv->phylink, pause); 431 - } 482 + phylink_ethtool_get_pauseparam(priv->phylink, pause); 432 483 } 433 484 434 485 static int ··· 433 492 { 434 493 struct stmmac_priv *priv = netdev_priv(netdev); 435 494 436 - if (priv->hw->pcs) { 437 - pause->autoneg = 1; 438 - return 0; 439 - } else { 440 - return phylink_ethtool_set_pauseparam(priv->phylink, pause); 441 - } 495 + return phylink_ethtool_set_pauseparam(priv->phylink, pause); 442 496 } 443 497 444 498 static u64 stmmac_get_rx_normal_irq_n(struct stmmac_priv *priv, int q)
+33 -35
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
··· 46 46 #include "stmmac_ptp.h" 47 47 #include "stmmac_fpe.h" 48 48 #include "stmmac.h" 49 + #include "stmmac_pcs.h" 49 50 #include "stmmac_xdp.h" 50 51 #include <linux/reset.h> 51 52 #include <linux/of_mdio.h> ··· 851 850 return pcs; 852 851 } 853 852 853 + /* The PCS control register is only relevant for SGMII, TBI and RTBI 854 + * modes. We no longer support TBI or RTBI, so only configure this 855 + * register when operating in SGMII mode with the integrated PCS. 856 + */ 857 + if (priv->hw->pcs & STMMAC_PCS_SGMII && priv->integrated_pcs) 858 + return &priv->integrated_pcs->pcs; 859 + 854 860 return NULL; 855 861 } 856 862 ··· 1094 1086 static void stmmac_check_pcs_mode(struct stmmac_priv *priv) 1095 1087 { 1096 1088 int interface = priv->plat->phy_interface; 1089 + int speed = priv->plat->mac_port_sel_speed; 1097 1090 1098 - if (priv->dma_cap.pcs) { 1099 - if ((interface == PHY_INTERFACE_MODE_RGMII) || 1100 - (interface == PHY_INTERFACE_MODE_RGMII_ID) || 1101 - (interface == PHY_INTERFACE_MODE_RGMII_RXID) || 1102 - (interface == PHY_INTERFACE_MODE_RGMII_TXID)) { 1103 - netdev_dbg(priv->dev, "PCS RGMII support enabled\n"); 1104 - priv->hw->pcs = STMMAC_PCS_RGMII; 1105 - } else if (interface == PHY_INTERFACE_MODE_SGMII) { 1106 - netdev_dbg(priv->dev, "PCS SGMII support enabled\n"); 1107 - priv->hw->pcs = STMMAC_PCS_SGMII; 1091 + if (priv->dma_cap.pcs && interface == PHY_INTERFACE_MODE_SGMII) { 1092 + netdev_dbg(priv->dev, "PCS SGMII support enabled\n"); 1093 + priv->hw->pcs = STMMAC_PCS_SGMII; 1094 + 1095 + switch (speed) { 1096 + case SPEED_10: 1097 + case SPEED_100: 1098 + case SPEED_1000: 1099 + priv->hw->reverse_sgmii_enable = true; 1100 + break; 1101 + 1102 + default: 1103 + dev_warn(priv->device, "invalid port speed\n"); 1104 + fallthrough; 1105 + case 0: 1106 + priv->hw->reverse_sgmii_enable = false; 1107 + break; 1108 1108 } 1109 1109 } 1110 1110 } ··· 3459 3443 stmmac_set_umac_addr(priv, priv->hw, dev->dev_addr, 0); 3460 3444 phylink_rx_clk_stop_unblock(priv->phylink); 3461 3445 3462 - /* PS and related bits will be programmed according to the speed */ 3463 - if (priv->hw->pcs) { 3464 - int speed = priv->plat->mac_port_sel_speed; 3465 - 3466 - if ((speed == SPEED_10) || (speed == SPEED_100) || 3467 - (speed == SPEED_1000)) { 3468 - priv->hw->ps = speed; 3469 - } else { 3470 - dev_warn(priv->device, "invalid port speed\n"); 3471 - priv->hw->ps = 0; 3472 - } 3473 - } 3474 - 3475 3446 /* Initialize the MAC Core */ 3476 3447 stmmac_core_init(priv, priv->hw, dev); 3477 3448 ··· 3494 3491 priv->rx_riwt[queue], queue); 3495 3492 } 3496 3493 } 3497 - 3498 - if (priv->hw->pcs) 3499 - stmmac_pcs_ctrl_ane(priv, 1, priv->hw->ps, 0); 3500 3494 3501 3495 /* set TX and RX rings length */ 3502 3496 stmmac_set_rings_length(priv); ··· 6001 6001 for (queue = 0; queue < queues_count; queue++) 6002 6002 stmmac_host_mtl_irq_status(priv, priv->hw, queue); 6003 6003 6004 - /* PCS link status */ 6005 - if (priv->hw->pcs && 6006 - !(priv->plat->flags & STMMAC_FLAG_HAS_INTEGRATED_PCS)) { 6007 - if (priv->xstats.pcs_link) 6008 - netif_carrier_on(priv->dev); 6009 - else 6010 - netif_carrier_off(priv->dev); 6011 - } 6012 - 6013 6004 stmmac_timestamp_interrupt(priv, priv); 6014 6005 } 6015 6006 } ··· 7239 7248 dev_info(priv->device, 7240 7249 "Enable RX Mitigation via HW Watchdog Timer\n"); 7241 7250 } 7251 + 7252 + /* Unimplemented PCS init (as indicated by stmmac_do_callback() 7253 + * perversely returning -EINVAL) is non-fatal. 7254 + */ 7255 + ret = stmmac_mac_pcs_init(priv); 7256 + if (ret != -EINVAL) 7257 + return ret; 7242 7258 7243 7259 return 0; 7244 7260 }
+47
drivers/net/ethernet/stmicro/stmmac/stmmac_pcs.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + #include "stmmac.h" 3 + #include "stmmac_pcs.h" 4 + 5 + static void dwmac_integrated_pcs_get_state(struct phylink_pcs *pcs, 6 + unsigned int neg_mode, 7 + struct phylink_link_state *state) 8 + { 9 + state->link = false; 10 + } 11 + 12 + static int dwmac_integrated_pcs_config(struct phylink_pcs *pcs, 13 + unsigned int neg_mode, 14 + phy_interface_t interface, 15 + const unsigned long *advertising, 16 + bool permit_pause_to_mac) 17 + { 18 + struct stmmac_pcs *spcs = phylink_pcs_to_stmmac_pcs(pcs); 19 + 20 + dwmac_ctrl_ane(spcs->base, 0, 1, spcs->priv->hw->reverse_sgmii_enable); 21 + 22 + return 0; 23 + } 24 + 25 + static const struct phylink_pcs_ops dwmac_integrated_pcs_ops = { 26 + .pcs_get_state = dwmac_integrated_pcs_get_state, 27 + .pcs_config = dwmac_integrated_pcs_config, 28 + }; 29 + 30 + int stmmac_integrated_pcs_init(struct stmmac_priv *priv, unsigned int offset) 31 + { 32 + struct stmmac_pcs *spcs; 33 + 34 + spcs = devm_kzalloc(priv->device, sizeof(*spcs), GFP_KERNEL); 35 + if (!spcs) 36 + return -ENOMEM; 37 + 38 + spcs->priv = priv; 39 + spcs->base = priv->ioaddr + offset; 40 + spcs->pcs.ops = &dwmac_integrated_pcs_ops; 41 + 42 + __set_bit(PHY_INTERFACE_MODE_SGMII, spcs->pcs.supported_interfaces); 43 + 44 + priv->integrated_pcs = spcs; 45 + 46 + return 0; 47 + }
+18 -5
drivers/net/ethernet/stmicro/stmmac/stmmac_pcs.h
··· 9 9 #ifndef __STMMAC_PCS_H__ 10 10 #define __STMMAC_PCS_H__ 11 11 12 + #include <linux/phylink.h> 12 13 #include <linux/slab.h> 13 14 #include <linux/io.h> 14 15 #include "common.h" ··· 47 46 #define GMAC_ANE_RFE_SHIFT 12 48 47 #define GMAC_ANE_ACK BIT(14) 49 48 49 + struct stmmac_priv; 50 + 51 + struct stmmac_pcs { 52 + struct stmmac_priv *priv; 53 + void __iomem *base; 54 + struct phylink_pcs pcs; 55 + }; 56 + 57 + static inline struct stmmac_pcs * 58 + phylink_pcs_to_stmmac_pcs(struct phylink_pcs *pcs) 59 + { 60 + return container_of(pcs, struct stmmac_pcs, pcs); 61 + } 62 + 63 + int stmmac_integrated_pcs_init(struct stmmac_priv *priv, unsigned int offset); 64 + 50 65 /** 51 66 * dwmac_pcs_isr - TBI, RTBI, or SGMII PHY ISR 52 67 * @ioaddr: IO registers pointer ··· 99 82 * @reg: Base address of the AN Control Register. 100 83 * @ane: to enable the auto-negotiation 101 84 * @srgmi_ral: to manage MAC-2-MAC SGMII connections. 102 - * @loopback: to cause the PHY to loopback tx data into rx path. 103 85 * Description: this is the main function to configure the AN control register 104 86 * and init the ANE, select loopback (usually for debugging purpose) and 105 87 * configure SGMII RAL. 106 88 */ 107 89 static inline void dwmac_ctrl_ane(void __iomem *ioaddr, u32 reg, bool ane, 108 - bool srgmi_ral, bool loopback) 90 + bool srgmi_ral) 109 91 { 110 92 u32 value = readl(ioaddr + GMAC_AN_CTRL(reg)); 111 93 ··· 119 103 */ 120 104 if (srgmi_ral) 121 105 value |= GMAC_AN_CTRL_SGMRAL; 122 - 123 - if (loopback) 124 - value |= GMAC_AN_CTRL_ELE; 125 106 126 107 writel(value, ioaddr + GMAC_AN_CTRL(reg)); 127 108 }
-1
include/linux/stmmac.h
··· 171 171 u32 mtl_low_cred_offset; 172 172 }; 173 173 174 - #define STMMAC_FLAG_HAS_INTEGRATED_PCS BIT(0) 175 174 #define STMMAC_FLAG_SPH_DISABLE BIT(1) 176 175 #define STMMAC_FLAG_USE_PHY_WOL BIT(2) 177 176 #define STMMAC_FLAG_HAS_SUN8I BIT(3)