diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2024-07-16 19:28:34 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2024-07-16 19:28:34 -0700 |
commit | 51835949dda3783d4639cfa74ce13a3c9829de00 (patch) | |
tree | 2b593de5eba6ecc73f7c58fc65fdaffae45c7323 /drivers/net/ethernet/stmicro/stmmac | |
parent | 0434dbe32053d07d658165be681505120c6b1abc (diff) | |
parent | 77ae5e5b00720372af2860efdc4bc652ac682696 (diff) |
Merge tag 'net-next-6.11' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-nextHEADmaster
Pull networking updates from Jakub Kicinski:
"Not much excitement - a handful of large patchsets (devmem among them)
did not make it in time.
Core & protocols:
- Use local_lock in addition to local_bh_disable() to protect per-CPU
resources in networking, a step closer for local_bh_disable() not
to act as a big lock on PREEMPT_RT
- Use flex array for netdevice priv area, ensure its cache alignment
- Add a sysctl knob to allow user to specify a default rto_min at
socket init time. Bit of a big hammer but multiple companies were
independently carrying such patch downstream so clearly it's useful
- Support scheduling transmission of packets based on CLOCK_TAI
- Un-pin TCP TIMEWAIT timer to avoid it firing on CPUs later cordoned
off using cpusets
- Support multiple L2TPv3 UDP tunnels using the same 5-tuple address
- Allow configuration of multipath hash seed, to both allow
synchronizing hashing of two routers, and preventing partial
accidental sync
- Improve TCP compliance with RFC 9293 for simultaneous connect()
- Support sending NAT keepalives in IPsec ESP in UDP states.
Userspace IKE daemon had to do this before, but the kernel can
better keep track of it
- Support sending supervision HSR frames with MAC addresses stored in
ProxyNodeTable when RedBox (i.e. HSR-SAN) is enabled
- Introduce IPPROTO_SMC for selecting SMC when socket is created
- Allow UDP GSO transmit from devices with no checksum offload
- openvswitch: add packet sampling via psample, separating the
sampled traffic from "upcall" packets sent to user space for
forwarding
- nf_tables: shrink memory consumption for transaction objects
Things we sprinkled into general kernel code:
- Power Sequencing subsystem (used by Qualcomm Bluetooth driver for
QCA6390) [ Already merged separately - Linus ]
- Add IRQ information in sysfs for auxiliary bus
- Introduce guard definition for local_lock
- Add aligned flavor of __cacheline_group_{begin, end}() markings for
grouping fields in structures
BPF:
- Notify user space (via epoll) when a struct_ops object is getting
detached/unregistered
- Add new kfuncs for a generic, open-coded bits iterator
- Enable BPF programs to declare arrays of kptr, bpf_rb_root, and
bpf_list_head
- Support resilient split BTF which cuts down on duplication and
makes BTF as compact as possible WRT BTF from modules
- Add support for dumping kfunc prototypes from BTF which enables
both detecting as well as dumping compilable prototypes for kfuncs
- riscv64 BPF JIT improvements in particular to add 12-argument
support for BPF trampolines and to utilize bpf_prog_pack for the
latter
- Add the capability to offload the netfilter flowtable in XDP layer
through kfuncs
Driver API:
- Allow users to configure IRQ tresholds between which automatic IRQ
moderation can choose
- Expand Power Sourcing (PoE) status with power, class and failure
reason. Support setting power limits
- Track additional RSS contexts in the core, make sure configuration
changes don't break them
- Support IPsec crypto offload for IPv6 ESP and IPv4 UDP-encapsulated
ESP data paths
- Support updating firmware on SFP modules
Tests and tooling:
- mptcp: use net/lib.sh to manage netns
- TCP-AO and TCP-MD5: replace debug prints used by tests with
tracepoints
- openvswitch: make test self-contained (don't depend on OvS CLI
tools)
Drivers:
- Ethernet high-speed NICs:
- Broadcom (bnxt):
- increase the max total outstanding PTP TX packets to 4
- add timestamping statistics support
- implement netdev_queue_mgmt_ops
- support new RSS context API
- Intel (100G, ice, idpf):
- implement FEC statistics and dumping signal quality indicators
- support E825C products (with 56Gbps PHYs)
- nVidia/Mellanox:
- support HW-GRO
- mlx4/mlx5: support per-queue statistics via netlink
- obey the max number of EQs setting in sub-functions
- AMD/Solarflare:
- support new RSS context API
- AMD/Pensando:
- ionic: rework fix for doorbell miss to lower overhead and
skip it on new HW
- Wangxun:
- txgbe: support Flow Director perfect filters
- Ethernet NICs consumer, embedded and virtual:
- Add driver for Tehuti Networks TN40xx chips
- Add driver for Meta's internal NIC chips
- Add driver for Ethernet MAC on Airoha EN7581 SoCs
- Add driver for Renesas Ethernet-TSN devices
- Google cloud vNIC:
- flow steering support
- Microsoft vNIC:
- support page sizes other than 4KB on ARM64
- vmware vNIC:
- support latency measurement (update to version 9)
- VirtIO net:
- support for Byte Queue Limits
- support configuring thresholds for automatic IRQ moderation
- support for AF_XDP Rx zero-copy
- Synopsys (stmmac):
- support for STM32MP13 SoC
- let platforms select the right PCS implementation
- TI:
- icssg-prueth: add multicast filtering support
- icssg-prueth: enable PTP timestamping and PPS
- Renesas:
- ravb: improve Rx performance 30-400% by using page pool,
theaded NAPI and timer-based IRQ coalescing
- ravb: add MII support for R-Car V4M
- Cadence (macb):
- macb: add ARP support to Wake-On-LAN
- Cortina:
- use phylib for RX and TX pause configuration
- Ethernet switches:
- nVidia/Mellanox:
- support configuration of multipath hash seed
- report more accurate max MTU
- use page_pool to improve Rx performance
- MediaTek:
- mt7530: add support for bridge port isolation
- Qualcomm:
- qca8k: add support for bridge port isolation
- Microchip:
- lan9371/2: add 100BaseTX PHY support
- NXP:
- vsc73xx: implement VLAN operations
- Ethernet PHYs:
- aquantia: enable support for aqr115c
- aquantia: add support for PHY LEDs
- realtek: add support for rtl8224 2.5Gbps PHY
- xpcs: add memory-mapped device support
- add BroadR-Reach link mode and support in Broadcom's PHY driver
- CAN:
- add document for ISO 15765-2 protocol support
- mcp251xfd: workaround for erratum DS80000789E, use timestamps to
catch when device returns incorrect FIFO status
- WiFi:
- mac80211/cfg80211:
- parse Transmit Power Envelope (TPE) data in mac80211 instead
of in drivers
- improvements for 6 GHz regulatory flexibility
- multi-link improvements
- support multiple radios per wiphy
- remove DEAUTH_NEED_MGD_TX_PREP flag
- Intel (iwlwifi):
- bump FW API to 91 for BZ/SC devices
- report 64-bit radiotap timestamp
- enable P2P low latency by default
- handle Transmit Power Envelope (TPE) advertised by AP
- remove support for older FW for new devices
- fast resume (keeping the device configured)
- mvm: re-enable Multi-Link Operation (MLO)
- aggregation (A-MSDU) optimizations
- MediaTek (mt76):
- mt7925 Multi-Link Operation (MLO) support
- Qualcomm (ath10k):
- LED support for various chipsets
- Qualcomm (ath12k):
- remove unsupported Tx monitor handling
- support channel 2 in 6 GHz band
- support Spatial Multiplexing Power Save (SMPS) in 6 GHz band
- supprt multiple BSSID (MBSSID) and Enhanced Multi-BSSID
Advertisements (EMA)
- support dynamic VLAN
- add panic handler for resetting the firmware state
- DebugFS support for datapath statistics
- WCN7850: support for Wake on WLAN
- Microchip (wilc1000):
- read MAC address during probe to make it visible to user space
- suspend/resume improvements
- TI (wl18xx):
- support newer firmware versions
- RealTek (rtw89):
- preparation for RTL8852BE-VT support
- Wake on WLAN support for WiFi 6 chips
- 36-bit PCI DMA support
- RealTek (rtlwifi):
- RTL8192DU support
- Broadcom (brcmfmac):
- Management Frame Protection support (to enable WPA3)
- Bluetooth:
- qualcomm: use the power sequencer for QCA6390
- btusb: mediatek: add ISO data transmission functions
- hci_bcm4377: add BCM4388 support
- btintel: add support for BlazarU core
- btintel: add support for Whale Peak2
- btnxpuart: add support for AW693 A1 chipset
- btnxpuart: add support for IW615 chipset
- btusb: add Realtek RTL8852BE support ID 0x13d3:0x3591"
* tag 'net-next-6.11' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next: (1589 commits)
eth: fbnic: Fix spelling mistake "tiggerring" -> "triggering"
tcp: Replace strncpy() with strscpy()
wifi: ath12k: fix build vs old compiler
tcp: Don't access uninit tcp_rsk(req)->ao_keyid in tcp_create_openreq_child().
eth: fbnic: Write the TCAM tables used for RSS control and Rx to host
eth: fbnic: Add L2 address programming
eth: fbnic: Add basic Rx handling
eth: fbnic: Add basic Tx handling
eth: fbnic: Add link detection
eth: fbnic: Add initial messaging to notify FW of our presence
eth: fbnic: Implement Rx queue alloc/start/stop/free
eth: fbnic: Implement Tx queue alloc/start/stop/free
eth: fbnic: Allocate a netdevice and napi vectors with queues
eth: fbnic: Add FW communication mechanism
eth: fbnic: Add message parsing for FW messages
eth: fbnic: Add register init to set PCIe/Ethernet device config
eth: fbnic: Allocate core device specific structures and devlink interface
eth: fbnic: Add scaffolding for Meta's NIC driver
PCI: Add Meta Platforms vendor ID
net/sched: cls_flower: propagate tca[TCA_OPTIONS] to NL_REQ_ATTR_CHECK
...
Diffstat (limited to 'drivers/net/ethernet/stmicro/stmmac')
19 files changed, 353 insertions, 191 deletions
diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h index 9cd62b2110a1..cd36ff4da68c 100644 --- a/drivers/net/ethernet/stmicro/stmmac/common.h +++ b/drivers/net/ethernet/stmicro/stmmac/common.h @@ -271,8 +271,6 @@ struct stmmac_safety_stats { /* PCS defines */ #define STMMAC_PCS_RGMII (1 << 0) #define STMMAC_PCS_SGMII (1 << 1) -#define STMMAC_PCS_TBI (1 << 2) -#define STMMAC_PCS_RTBI (1 << 3) #define SF_DMA_MODE 1 /* DMA STORE-AND-FORWARD Operation Mode */ diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c index e73fa34237d3..83ad7c7935e3 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c @@ -248,7 +248,7 @@ static void intel_speed_mode_2500(struct net_device *ndev, void *intel_data) dev_info(priv->device, "Link Speed Mode: 2.5Gbps\n"); priv->plat->max_speed = 2500; priv->plat->phy_interface = PHY_INTERFACE_MODE_2500BASEX; - priv->plat->mdio_bus_data->xpcs_an_inband = false; + priv->plat->mdio_bus_data->default_an_inband = false; } else { priv->plat->max_speed = 1000; } @@ -444,6 +444,16 @@ static void common_default_data(struct plat_stmmacenet_data *plat) plat->rx_queues_cfg[0].pkt_route = 0x0; } +static struct phylink_pcs *intel_mgbe_select_pcs(struct stmmac_priv *priv, + phy_interface_t interface) +{ + /* plat->mdio_bus_data->has_xpcs has been set true, so there + * should always be an XPCS. The original code would always + * return this if present. + */ + return &priv->hw->xpcs->pcs; +} + static int intel_mgbe_common_data(struct pci_dev *pdev, struct plat_stmmacenet_data *plat) { @@ -586,19 +596,9 @@ static int intel_mgbe_common_data(struct pci_dev *pdev, /* Intel mgbe SGMII interface uses pcs-xcps */ if (plat->phy_interface == PHY_INTERFACE_MODE_SGMII || plat->phy_interface == PHY_INTERFACE_MODE_1000BASEX) { - plat->mdio_bus_data->has_xpcs = true; - plat->mdio_bus_data->xpcs_an_inband = true; - } - - /* For fixed-link setup, we clear xpcs_an_inband */ - if (fwnode) { - struct fwnode_handle *fixed_node; - - fixed_node = fwnode_get_named_child_node(fwnode, "fixed-link"); - if (fixed_node) - plat->mdio_bus_data->xpcs_an_inband = false; - - fwnode_handle_put(fixed_node); + plat->mdio_bus_data->pcs_mask = BIT(INTEL_MGBE_XPCS_ADDR); + plat->mdio_bus_data->default_an_inband = true; + plat->select_pcs = intel_mgbe_select_pcs; } /* Ensure mdio bus scan skips intel serdes and pcs-xpcs */ diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c index 466c4002f00d..901a3c1959fa 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c @@ -21,6 +21,7 @@ #define RGMII_IO_MACRO_CONFIG2 0x1C #define RGMII_IO_MACRO_DEBUG1 0x20 #define EMAC_SYSTEM_LOW_POWER_DEBUG 0x28 +#define EMAC_WRAPPER_SGMII_PHY_CNTRL1 0xf4 /* RGMII_IO_MACRO_CONFIG fields */ #define RGMII_CONFIG_FUNC_CLK_EN BIT(30) @@ -79,6 +80,9 @@ #define ETHQOS_MAC_CTRL_SPEED_MODE BIT(14) #define ETHQOS_MAC_CTRL_PORT_SEL BIT(15) +/* EMAC_WRAPPER_SGMII_PHY_CNTRL1 bits */ +#define SGMII_PHY_CNTRL1_SGMII_TX_TO_RX_LOOPBACK_EN BIT(3) + #define SGMII_10M_RX_CLK_DVDR 0x31 struct ethqos_emac_por { @@ -95,6 +99,7 @@ struct ethqos_emac_driver_data { bool has_integrated_pcs; u32 dma_addr_width; struct dwmac4_addrs dwmac4_addrs; + bool needs_sgmii_loopback; }; struct qcom_ethqos { @@ -114,6 +119,7 @@ struct qcom_ethqos { unsigned int num_por; bool rgmii_config_loopback_en; bool has_emac_ge_3; + bool needs_sgmii_loopback; }; static int rgmii_readl(struct qcom_ethqos *ethqos, unsigned int offset) @@ -191,8 +197,22 @@ ethqos_update_link_clk(struct qcom_ethqos *ethqos, unsigned int speed) clk_set_rate(ethqos->link_clk, ethqos->link_clk_rate); } +static void +qcom_ethqos_set_sgmii_loopback(struct qcom_ethqos *ethqos, bool enable) +{ + if (!ethqos->needs_sgmii_loopback || + ethqos->phy_mode != PHY_INTERFACE_MODE_2500BASEX) + return; + + rgmii_updatel(ethqos, + SGMII_PHY_CNTRL1_SGMII_TX_TO_RX_LOOPBACK_EN, + enable ? SGMII_PHY_CNTRL1_SGMII_TX_TO_RX_LOOPBACK_EN : 0, + EMAC_WRAPPER_SGMII_PHY_CNTRL1); +} + static void ethqos_set_func_clk_en(struct qcom_ethqos *ethqos) { + qcom_ethqos_set_sgmii_loopback(ethqos, true); rgmii_updatel(ethqos, RGMII_CONFIG_FUNC_CLK_EN, RGMII_CONFIG_FUNC_CLK_EN, RGMII_IO_MACRO_CONFIG); } @@ -277,6 +297,7 @@ static const struct ethqos_emac_driver_data emac_v4_0_0_data = { .has_emac_ge_3 = true, .link_clk_name = "phyaux", .has_integrated_pcs = true, + .needs_sgmii_loopback = true, .dma_addr_width = 36, .dwmac4_addrs = { .dma_chan = 0x00008100, @@ -607,6 +628,14 @@ static int ethqos_configure_rgmii(struct qcom_ethqos *ethqos) return 0; } +static void ethqos_set_serdes_speed(struct qcom_ethqos *ethqos, int speed) +{ + if (ethqos->serdes_speed != speed) { + phy_set_speed(ethqos->serdes_phy, speed); + ethqos->serdes_speed = speed; + } +} + /* On interface toggle MAC registers gets reset. * Configure MAC block for SGMII on ethernet phy link up */ @@ -624,9 +653,7 @@ static int ethqos_configure_sgmii(struct qcom_ethqos *ethqos) rgmii_updatel(ethqos, RGMII_CONFIG2_RGMII_CLK_SEL_CFG, RGMII_CONFIG2_RGMII_CLK_SEL_CFG, RGMII_IO_MACRO_CONFIG2); - if (ethqos->serdes_speed != SPEED_2500) - phy_set_speed(ethqos->serdes_phy, SPEED_2500); - ethqos->serdes_speed = SPEED_2500; + ethqos_set_serdes_speed(ethqos, SPEED_2500); stmmac_pcs_ctrl_ane(priv, priv->ioaddr, 0, 0, 0); break; case SPEED_1000: @@ -634,16 +661,12 @@ static int ethqos_configure_sgmii(struct qcom_ethqos *ethqos) rgmii_updatel(ethqos, RGMII_CONFIG2_RGMII_CLK_SEL_CFG, RGMII_CONFIG2_RGMII_CLK_SEL_CFG, RGMII_IO_MACRO_CONFIG2); - if (ethqos->serdes_speed != SPEED_1000) - phy_set_speed(ethqos->serdes_phy, SPEED_1000); - ethqos->serdes_speed = SPEED_1000; + ethqos_set_serdes_speed(ethqos, SPEED_1000); stmmac_pcs_ctrl_ane(priv, priv->ioaddr, 1, 0, 0); break; case SPEED_100: val |= ETHQOS_MAC_CTRL_PORT_SEL | ETHQOS_MAC_CTRL_SPEED_MODE; - if (ethqos->serdes_speed != SPEED_1000) - phy_set_speed(ethqos->serdes_phy, SPEED_1000); - ethqos->serdes_speed = SPEED_1000; + ethqos_set_serdes_speed(ethqos, SPEED_1000); stmmac_pcs_ctrl_ane(priv, priv->ioaddr, 1, 0, 0); break; case SPEED_10: @@ -653,9 +676,7 @@ static int ethqos_configure_sgmii(struct qcom_ethqos *ethqos) FIELD_PREP(RGMII_CONFIG_SGMII_CLK_DVDR, SGMII_10M_RX_CLK_DVDR), RGMII_IO_MACRO_CONFIG); - if (ethqos->serdes_speed != SPEED_1000) - phy_set_speed(ethqos->serdes_phy, ethqos->speed); - ethqos->serdes_speed = SPEED_1000; + ethqos_set_serdes_speed(ethqos, SPEED_1000); stmmac_pcs_ctrl_ane(priv, priv->ioaddr, 1, 0, 0); break; } @@ -665,6 +686,14 @@ static int ethqos_configure_sgmii(struct qcom_ethqos *ethqos) return val; } +static void qcom_ethqos_speed_mode_2500(struct net_device *ndev, void *data) +{ + struct stmmac_priv *priv = netdev_priv(ndev); + + priv->plat->max_speed = 2500; + priv->plat->phy_interface = PHY_INTERFACE_MODE_2500BASEX; +} + static int ethqos_configure(struct qcom_ethqos *ethqos) { return ethqos->configure_func(ethqos); @@ -674,6 +703,7 @@ static void ethqos_fix_mac_speed(void *priv, unsigned int speed, unsigned int mo { struct qcom_ethqos *ethqos = priv; + qcom_ethqos_set_sgmii_loopback(ethqos, false); ethqos->speed = speed; ethqos_update_link_clk(ethqos, speed); ethqos_configure(ethqos); @@ -787,6 +817,9 @@ static int qcom_ethqos_probe(struct platform_device *pdev) case PHY_INTERFACE_MODE_RGMII_TXID: ethqos->configure_func = ethqos_configure_rgmii; break; + case PHY_INTERFACE_MODE_2500BASEX: + plat_dat->speed_mode_2500 = qcom_ethqos_speed_mode_2500; + fallthrough; case PHY_INTERFACE_MODE_SGMII: ethqos->configure_func = ethqos_configure_sgmii; break; @@ -809,6 +842,7 @@ static int qcom_ethqos_probe(struct platform_device *pdev) ethqos->num_por = data->num_por; ethqos->rgmii_config_loopback_en = data->rgmii_config_loopback_en; ethqos->has_emac_ge_3 = data->has_emac_ge_3; + ethqos->needs_sgmii_loopback = data->needs_sgmii_loopback; ethqos->link_clk = devm_clk_get(dev, data->link_clk_name ?: "rgmii"); if (IS_ERR(ethqos->link_clk)) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rzn1.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rzn1.c index 848cf3c01f4a..59a7bd560f96 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rzn1.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rzn1.c @@ -39,6 +39,12 @@ static void rzn1_dwmac_pcs_exit(struct stmmac_priv *priv) miic_destroy(priv->hw->phylink_pcs); } +static struct phylink_pcs *rzn1_dwmac_select_pcs(struct stmmac_priv *priv, + phy_interface_t interface) +{ + return priv->hw->phylink_pcs; +} + static int rzn1_dwmac_probe(struct platform_device *pdev) { struct plat_stmmacenet_data *plat_dat; @@ -57,6 +63,7 @@ static int rzn1_dwmac_probe(struct platform_device *pdev) plat_dat->bsp_priv = plat_dat; plat_dat->pcs_init = rzn1_dwmac_pcs_init; plat_dat->pcs_exit = rzn1_dwmac_pcs_exit; + plat_dat->select_pcs = rzn1_dwmac_select_pcs; ret = stmmac_dvr_probe(dev, plat_dat, &stmmac_res); if (ret) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c index b3d45f9dfb55..fdb4c773ec98 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c @@ -429,6 +429,12 @@ static void socfpga_dwmac_pcs_exit(struct stmmac_priv *priv) lynx_pcs_destroy(priv->hw->phylink_pcs); } +static struct phylink_pcs *socfpga_dwmac_select_pcs(struct stmmac_priv *priv, + phy_interface_t interface) +{ + return priv->hw->phylink_pcs; +} + static int socfpga_dwmac_probe(struct platform_device *pdev) { struct plat_stmmacenet_data *plat_dat; @@ -478,6 +484,7 @@ static int socfpga_dwmac_probe(struct platform_device *pdev) plat_dat->fix_mac_speed = socfpga_dwmac_fix_mac_speed; plat_dat->pcs_init = socfpga_dwmac_pcs_init; plat_dat->pcs_exit = socfpga_dwmac_pcs_exit; + plat_dat->select_pcs = socfpga_dwmac_select_pcs; ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); if (ret) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c index c92dfc4ecf57..c1732955a697 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c @@ -53,12 +53,23 @@ #define SYSCFG_MCU_ETH_SEL_MII 0 #define SYSCFG_MCU_ETH_SEL_RMII 1 -/* STM32MP1 register definitions +/* STM32MP2 register definitions */ +#define SYSCFG_MP2_ETH_MASK GENMASK(31, 0) + +#define SYSCFG_ETHCR_ETH_PTP_CLK_SEL BIT(2) +#define SYSCFG_ETHCR_ETH_CLK_SEL BIT(1) +#define SYSCFG_ETHCR_ETH_REF_CLK_SEL BIT(0) + +#define SYSCFG_ETHCR_ETH_SEL_MII 0 +#define SYSCFG_ETHCR_ETH_SEL_RGMII BIT(4) +#define SYSCFG_ETHCR_ETH_SEL_RMII BIT(6) + +/* STM32MPx register definitions * * Below table summarizes the clock requirement and clock sources for * supported phy interface modes. * __________________________________________________________________________ - *|PHY_MODE | Normal | PHY wo crystal| PHY wo crystal |No 125Mhz from PHY| + *|PHY_MODE | Normal | PHY wo crystal| PHY wo crystal |No 125MHz from PHY| *| | | 25MHz | 50MHz | | * --------------------------------------------------------------------------- *| MII | - | eth-ck | n/a | n/a | @@ -90,6 +101,7 @@ struct stm32_dwmac { int eth_ref_clk_sel_reg; int irq_pwr_wakeup; u32 mode_reg; /* MAC glue-logic mode register */ + u32 mode_mask; struct regmap *regmap; u32 speed; const struct stm32_ops *ops; @@ -102,8 +114,9 @@ struct stm32_ops { void (*resume)(struct stm32_dwmac *dwmac); int (*parse_data)(struct stm32_dwmac *dwmac, struct device *dev); - u32 syscfg_eth_mask; bool clk_rx_enable_in_suspend; + bool is_mp13, is_mp2; + u32 syscfg_clr_off; }; static int stm32_dwmac_clk_enable(struct stm32_dwmac *dwmac, bool resume) @@ -157,65 +170,190 @@ static int stm32_dwmac_init(struct plat_stmmacenet_data *plat_dat, bool resume) return stm32_dwmac_clk_enable(dwmac, resume); } -static int stm32mp1_set_mode(struct plat_stmmacenet_data *plat_dat) +static int stm32mp1_select_ethck_external(struct plat_stmmacenet_data *plat_dat) { struct stm32_dwmac *dwmac = plat_dat->bsp_priv; - u32 reg = dwmac->mode_reg, clk_rate; - int val; - clk_rate = clk_get_rate(dwmac->clk_eth_ck); - dwmac->enable_eth_ck = false; switch (plat_dat->mac_interface) { case PHY_INTERFACE_MODE_MII: - if (clk_rate == ETH_CK_F_25M && dwmac->ext_phyclk) - dwmac->enable_eth_ck = true; - val = SYSCFG_PMCR_ETH_SEL_MII; - pr_debug("SYSCFG init : PHY_INTERFACE_MODE_MII\n"); + dwmac->enable_eth_ck = dwmac->ext_phyclk; + return 0; + case PHY_INTERFACE_MODE_GMII: + dwmac->enable_eth_ck = dwmac->eth_clk_sel_reg || + dwmac->ext_phyclk; + return 0; + case PHY_INTERFACE_MODE_RMII: + dwmac->enable_eth_ck = dwmac->eth_ref_clk_sel_reg || + dwmac->ext_phyclk; + return 0; + case PHY_INTERFACE_MODE_RGMII: + case PHY_INTERFACE_MODE_RGMII_ID: + case PHY_INTERFACE_MODE_RGMII_RXID: + case PHY_INTERFACE_MODE_RGMII_TXID: + dwmac->enable_eth_ck = dwmac->eth_clk_sel_reg || + dwmac->ext_phyclk; + return 0; + default: + dwmac->enable_eth_ck = false; + dev_err(dwmac->dev, "Mode %s not supported", + phy_modes(plat_dat->mac_interface)); + return -EINVAL; + } +} + +static int stm32mp1_validate_ethck_rate(struct plat_stmmacenet_data *plat_dat) +{ + struct stm32_dwmac *dwmac = plat_dat->bsp_priv; + const u32 clk_rate = clk_get_rate(dwmac->clk_eth_ck); + + if (!dwmac->enable_eth_ck) + return 0; + + switch (plat_dat->mac_interface) { + case PHY_INTERFACE_MODE_MII: + case PHY_INTERFACE_MODE_GMII: + if (clk_rate == ETH_CK_F_25M) + return 0; + break; + case PHY_INTERFACE_MODE_RMII: + if (clk_rate == ETH_CK_F_25M || clk_rate == ETH_CK_F_50M) + return 0; + break; + case PHY_INTERFACE_MODE_RGMII: + case PHY_INTERFACE_MODE_RGMII_ID: + case PHY_INTERFACE_MODE_RGMII_RXID: + case PHY_INTERFACE_MODE_RGMII_TXID: + if (clk_rate == ETH_CK_F_25M || clk_rate == ETH_CK_F_125M) + return 0; + break; + default: + break; + } + + dev_err(dwmac->dev, "Mode %s does not match eth-ck frequency %d Hz", + phy_modes(plat_dat->mac_interface), clk_rate); + return -EINVAL; +} + +static int stm32mp1_configure_pmcr(struct plat_stmmacenet_data *plat_dat) +{ + struct stm32_dwmac *dwmac = plat_dat->bsp_priv; + u32 reg = dwmac->mode_reg; + int val = 0; + + switch (plat_dat->mac_interface) { + case PHY_INTERFACE_MODE_MII: + /* + * STM32MP15xx supports both MII and GMII, STM32MP13xx MII only. + * SYSCFG_PMCSETR ETH_SELMII is present only on STM32MP15xx and + * acts as a selector between 0:GMII and 1:MII. As STM32MP13xx + * supports only MII, ETH_SELMII is not present. + */ + if (!dwmac->ops->is_mp13) /* Select MII mode on STM32MP15xx */ + val |= SYSCFG_PMCR_ETH_SEL_MII; break; case PHY_INTERFACE_MODE_GMII: val = SYSCFG_PMCR_ETH_SEL_GMII; - if (clk_rate == ETH_CK_F_25M && - (dwmac->eth_clk_sel_reg || dwmac->ext_phyclk)) { - dwmac->enable_eth_ck = true; + if (dwmac->enable_eth_ck) val |= SYSCFG_PMCR_ETH_CLK_SEL; - } - pr_debug("SYSCFG init : PHY_INTERFACE_MODE_GMII\n"); break; case PHY_INTERFACE_MODE_RMII: val = SYSCFG_PMCR_ETH_SEL_RMII; - if ((clk_rate == ETH_CK_F_25M || clk_rate == ETH_CK_F_50M) && - (dwmac->eth_ref_clk_sel_reg || dwmac->ext_phyclk)) { - dwmac->enable_eth_ck = true; + if (dwmac->enable_eth_ck) val |= SYSCFG_PMCR_ETH_REF_CLK_SEL; - } - pr_debug("SYSCFG init : PHY_INTERFACE_MODE_RMII\n"); break; case PHY_INTERFACE_MODE_RGMII: case PHY_INTERFACE_MODE_RGMII_ID: case PHY_INTERFACE_MODE_RGMII_RXID: case PHY_INTERFACE_MODE_RGMII_TXID: val = SYSCFG_PMCR_ETH_SEL_RGMII; - if ((clk_rate == ETH_CK_F_25M || clk_rate == ETH_CK_F_125M) && - (dwmac->eth_clk_sel_reg || dwmac->ext_phyclk)) { - dwmac->enable_eth_ck = true; + if (dwmac->enable_eth_ck) val |= SYSCFG_PMCR_ETH_CLK_SEL; - } - pr_debug("SYSCFG init : PHY_INTERFACE_MODE_RGMII\n"); break; default: - pr_debug("SYSCFG init : Do not manage %d interface\n", - plat_dat->mac_interface); + dev_err(dwmac->dev, "Mode %s not supported", + phy_modes(plat_dat->mac_interface)); /* Do not manage others interfaces */ return -EINVAL; } + dev_dbg(dwmac->dev, "Mode %s", phy_modes(plat_dat->mac_interface)); + + /* Shift value at correct ethernet MAC offset in SYSCFG_PMCSETR */ + val <<= ffs(dwmac->mode_mask) - ffs(SYSCFG_MP1_ETH_MASK); + /* Need to update PMCCLRR (clear register) */ - regmap_write(dwmac->regmap, reg + SYSCFG_PMCCLRR_OFFSET, - dwmac->ops->syscfg_eth_mask); + regmap_write(dwmac->regmap, dwmac->ops->syscfg_clr_off, + dwmac->mode_mask); /* Update PMCSETR (set register) */ return regmap_update_bits(dwmac->regmap, reg, - dwmac->ops->syscfg_eth_mask, val); + dwmac->mode_mask, val); +} + +static int stm32mp2_configure_syscfg(struct plat_stmmacenet_data *plat_dat) +{ + struct stm32_dwmac *dwmac = plat_dat->bsp_priv; + u32 reg = dwmac->mode_reg; + int val = 0; + + switch (plat_dat->mac_interface) { + case PHY_INTERFACE_MODE_MII: + /* ETH_REF_CLK_SEL bit in SYSCFG register is not applicable in MII mode */ + break; + case PHY_INTERFACE_MODE_RMII: + val = SYSCFG_ETHCR_ETH_SEL_RMII; + if (dwmac->enable_eth_ck) { + /* Internal clock ETH_CLK of 50MHz from RCC is used */ + val |= SYSCFG_ETHCR_ETH_REF_CLK_SEL; + } + break; + case PHY_INTERFACE_MODE_RGMII: + case PHY_INTERFACE_MODE_RGMII_ID: + case PHY_INTERFACE_MODE_RGMII_RXID: + case PHY_INTERFACE_MODE_RGMII_TXID: + val = SYSCFG_ETHCR_ETH_SEL_RGMII; + fallthrough; + case PHY_INTERFACE_MODE_GMII: + if (dwmac->enable_eth_ck) { + /* Internal clock ETH_CLK of 125MHz from RCC is used */ + val |= SYSCFG_ETHCR_ETH_CLK_SEL; + } + break; + default: + dev_err(dwmac->dev, "Mode %s not supported", + phy_modes(plat_dat->mac_interface)); + /* Do not manage others interfaces */ + return -EINVAL; + } + + dev_dbg(dwmac->dev, "Mode %s", phy_modes(plat_dat->mac_interface)); + + /* Select PTP (IEEE1588) clock selection from RCC (ck_ker_ethxptp) */ + val |= SYSCFG_ETHCR_ETH_PTP_CLK_SEL; + + /* Update ETHCR (set register) */ + return regmap_update_bits(dwmac->regmap, reg, + SYSCFG_MP2_ETH_MASK, val); +} + +static int stm32mp1_set_mode(struct plat_stmmacenet_data *plat_dat) +{ + struct stm32_dwmac *dwmac = plat_dat->bsp_priv; + int ret; + + ret = stm32mp1_select_ethck_external(plat_dat); + if (ret) + return ret; + + ret = stm32mp1_validate_ethck_rate(plat_dat); + if (ret) + return ret; + + if (!dwmac->ops->is_mp2) + return stm32mp1_configure_pmcr(plat_dat); + else + return stm32mp2_configure_syscfg(plat_dat); } static int stm32mcu_set_mode(struct plat_stmmacenet_data *plat_dat) @@ -227,21 +365,21 @@ static int stm32mcu_set_mode(struct plat_stmmacenet_data *plat_dat) switch (plat_dat->mac_interface) { case PHY_INTERFACE_MODE_MII: val = SYSCFG_MCU_ETH_SEL_MII; - pr_debug("SYSCFG init : PHY_INTERFACE_MODE_MII\n"); break; case PHY_INTERFACE_MODE_RMII: val = SYSCFG_MCU_ETH_SEL_RMII; - pr_debug("SYSCFG init : PHY_INTERFACE_MODE_RMII\n"); break; default: - pr_debug("SYSCFG init : Do not manage %d interface\n", - plat_dat->mac_interface); + dev_err(dwmac->dev, "Mode %s not supported", + phy_modes(plat_dat->mac_interface)); /* Do not manage others interfaces */ return -EINVAL; } + dev_dbg(dwmac->dev, "Mode %s", phy_modes(plat_dat->mac_interface)); + return regmap_update_bits(dwmac->regmap, reg, - dwmac->ops->syscfg_eth_mask, val << 23); + SYSCFG_MCU_ETH_MASK, val << 23); } static void stm32_dwmac_clk_disable(struct stm32_dwmac *dwmac, bool suspend) @@ -286,8 +424,24 @@ static int stm32_dwmac_parse_data(struct stm32_dwmac *dwmac, return PTR_ERR(dwmac->regmap); err = of_property_read_u32_index(np, "st,syscon", 1, &dwmac->mode_reg); - if (err) + if (err) { dev_err(dev, "Can't get sysconfig mode offset (%d)\n", err); + return err; + } + + if (dwmac->ops->is_mp2) + return 0; + + dwmac->mode_mask = SYSCFG_MP1_ETH_MASK; + err = of_property_read_u32_index(np, "st,syscon", 2, &dwmac->mode_mask); + if (err) { + if (dwmac->ops->is_mp13) { + dev_err(dev, "Sysconfig register mask must be set (%d)\n", err); + } else { + dev_dbg(dev, "Warning sysconfig register mask not set\n"); + err = 0; + } + } return err; } @@ -305,7 +459,7 @@ static int stm32mp1_parse_data(struct stm32_dwmac *dwmac, /* Gigabit Ethernet 125MHz clock selection. */ dwmac->eth_clk_sel_reg = of_property_read_bool(np, "st,eth-clk-sel"); - /* Ethernet 50Mhz RMII clock selection */ + /* Ethernet 50MHz RMII clock selection */ dwmac->eth_ref_clk_sel_reg = of_property_read_bool(np, "st,eth-ref-clk-sel"); @@ -478,8 +632,7 @@ static SIMPLE_DEV_PM_OPS(stm32_dwmac_pm_ops, stm32_dwmac_suspend, stm32_dwmac_resume); static struct stm32_ops stm32mcu_dwmac_data = { - .set_mode = stm32mcu_set_mode, - .syscfg_eth_mask = SYSCFG_MCU_ETH_MASK + .set_mode = stm32mcu_set_mode }; static struct stm32_ops stm32mp1_dwmac_data = { @@ -487,13 +640,35 @@ static struct stm32_ops stm32mp1_dwmac_data = { .suspend = stm32mp1_suspend, .resume = stm32mp1_resume, .parse_data = stm32mp1_parse_data, - .syscfg_eth_mask = SYSCFG_MP1_ETH_MASK, + .syscfg_clr_off = 0x44, + .is_mp13 = false, + .clk_rx_enable_in_suspend = true +}; + +static struct stm32_ops stm32mp13_dwmac_data = { + .set_mode = stm32mp1_set_mode, + .suspend = stm32mp1_suspend, + .resume = stm32mp1_resume, + .parse_data = stm32mp1_parse_data, + .syscfg_clr_off = 0x08, + .is_mp13 = true, + .clk_rx_enable_in_suspend = true +}; + +static struct stm32_ops stm32mp25_dwmac_data = { + .set_mode = stm32mp1_set_mode, + .suspend = stm32mp1_suspend, + .resume = stm32mp1_resume, + .parse_data = stm32mp1_parse_data, + .is_mp2 = true, .clk_rx_enable_in_suspend = true }; static const struct of_device_id stm32_dwmac_match[] = { { .compatible = "st,stm32-dwmac", .data = &stm32mcu_dwmac_data}, { .compatible = "st,stm32mp1-dwmac", .data = &stm32mp1_dwmac_data}, + { .compatible = "st,stm32mp13-dwmac", .data = &stm32mp13_dwmac_data}, + { .compatible = "st,stm32mp25-dwmac", .data = &stm32mp25_dwmac_data}, { } }; MODULE_DEVICE_TABLE(of, stm32_dwmac_match); diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c index 8555299443f4..d413d76a8936 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c @@ -15,7 +15,7 @@ #include <linux/crc32.h> #include <linux/slab.h> #include <linux/ethtool.h> -#include <asm/io.h> +#include <linux/io.h> #include "stmmac.h" #include "stmmac_pcs.h" #include "dwmac1000.h" @@ -404,11 +404,6 @@ static void dwmac1000_ctrl_ane(void __iomem *ioaddr, bool ane, bool srgmi_ral, dwmac_ctrl_ane(ioaddr, GMAC_PCS_BASE, ane, srgmi_ral, loopback); } -static void dwmac1000_rane(void __iomem *ioaddr, bool restart) -{ - dwmac_rane(ioaddr, GMAC_PCS_BASE, restart); -} - static void dwmac1000_get_adv_lp(void __iomem *ioaddr, struct rgmii_adv *adv) { dwmac_get_adv_lp(ioaddr, GMAC_PCS_BASE, adv); @@ -519,7 +514,6 @@ const struct stmmac_ops dwmac1000_ops = { .set_eee_pls = dwmac1000_set_eee_pls, .debug = dwmac1000_debug, .pcs_ctrl_ane = dwmac1000_ctrl_ane, - .pcs_rane = dwmac1000_rane, .pcs_get_adv_lp = dwmac1000_get_adv_lp, .set_mac_loopback = dwmac1000_set_mac_loopback, }; diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c index daf79cdbd3ec..adccdd816ea9 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c @@ -12,7 +12,7 @@ Author: Giuseppe Cavallaro <peppe.cavallaro@st.com> *******************************************************************************/ -#include <asm/io.h> +#include <linux/io.h> #include "dwmac1000.h" #include "dwmac_dma.h" diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c index 7667d103cd0e..14e847c0e1a9 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c @@ -15,7 +15,7 @@ *******************************************************************************/ #include <linux/crc32.h> -#include <asm/io.h> +#include <linux/io.h> #include "stmmac.h" #include "dwmac100.h" diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c index dea270f60cc3..b402fb54f613 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c @@ -14,7 +14,7 @@ Author: Giuseppe Cavallaro <peppe.cavallaro@st.com> *******************************************************************************/ -#include <asm/io.h> +#include <linux/io.h> #include "dwmac100.h" #include "dwmac_dma.h" diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c index b25774d69195..dbd9f93b2460 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c @@ -758,11 +758,6 @@ static void dwmac4_ctrl_ane(void __iomem *ioaddr, bool ane, bool srgmi_ral, dwmac_ctrl_ane(ioaddr, GMAC_PCS_BASE, ane, srgmi_ral, loopback); } -static void dwmac4_rane(void __iomem *ioaddr, bool restart) -{ - dwmac_rane(ioaddr, GMAC_PCS_BASE, restart); -} - static void dwmac4_get_adv_lp(void __iomem *ioaddr, struct rgmii_adv *adv) { dwmac_get_adv_lp(ioaddr, GMAC_PCS_BASE, adv); @@ -1215,7 +1210,6 @@ const struct stmmac_ops dwmac4_ops = { .set_eee_timer = dwmac4_set_eee_timer, .set_eee_pls = dwmac4_set_eee_pls, .pcs_ctrl_ane = dwmac4_ctrl_ane, - .pcs_rane = dwmac4_rane, .pcs_get_adv_lp = dwmac4_get_adv_lp, .debug = dwmac4_debug, .set_filter = dwmac4_set_filter, @@ -1260,7 +1254,6 @@ const struct stmmac_ops dwmac410_ops = { .set_eee_timer = dwmac4_set_eee_timer, .set_eee_pls = dwmac4_set_eee_pls, .pcs_ctrl_ane = dwmac4_ctrl_ane, - .pcs_rane = dwmac4_rane, .pcs_get_adv_lp = dwmac4_get_adv_lp, .debug = dwmac4_debug, .set_filter = dwmac4_set_filter, @@ -1309,7 +1302,6 @@ const struct stmmac_ops dwmac510_ops = { .set_eee_timer = dwmac4_set_eee_timer, .set_eee_pls = dwmac4_set_eee_pls, .pcs_ctrl_ane = dwmac4_ctrl_ane, - .pcs_rane = dwmac4_rane, .pcs_get_adv_lp = dwmac4_get_adv_lp, .debug = dwmac4_debug, .set_filter = dwmac4_set_filter, diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c index f8e7775bb633..6a987cf598e4 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c @@ -1554,9 +1554,6 @@ const struct stmmac_ops dwxgmac210_ops = { .reset_eee_mode = dwxgmac2_reset_eee_mode, .set_eee_timer = dwxgmac2_set_eee_timer, .set_eee_pls = dwxgmac2_set_eee_pls, - .pcs_ctrl_ane = NULL, - .pcs_rane = NULL, - .pcs_get_adv_lp = NULL, .debug = NULL, .set_filter = dwxgmac2_set_filter, .safety_feat_config = dwxgmac3_safety_feat_config, @@ -1614,9 +1611,6 @@ const struct stmmac_ops dwxlgmac2_ops = { .reset_eee_mode = dwxgmac2_reset_eee_mode, .set_eee_timer = dwxgmac2_set_eee_timer, .set_eee_pls = dwxgmac2_set_eee_pls, - .pcs_ctrl_ane = NULL, - .pcs_rane = NULL, - .pcs_get_adv_lp = NULL, .debug = NULL, .set_filter = dwxgmac2_set_filter, .safety_feat_config = dwxgmac3_safety_feat_config, diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h index 90384db228b5..97934ccba5b1 100644 --- a/drivers/net/ethernet/stmicro/stmmac/hwif.h +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h @@ -370,7 +370,6 @@ struct stmmac_ops { /* PCS calls */ void (*pcs_ctrl_ane)(void __iomem *ioaddr, bool ane, bool srgmi_ral, bool loopback); - void (*pcs_rane)(void __iomem *ioaddr, bool restart); void (*pcs_get_adv_lp)(void __iomem *ioaddr, struct rgmii_adv *adv); /* Safety Features */ int (*safety_feat_config)(void __iomem *ioaddr, unsigned int asp, @@ -484,8 +483,6 @@ struct stmmac_ops { stmmac_do_void_callback(__priv, mac, debug, __priv, __args) #define stmmac_pcs_ctrl_ane(__priv, __args...) \ stmmac_do_void_callback(__priv, mac, pcs_ctrl_ane, __args) -#define stmmac_pcs_rane(__priv, __args...) \ - stmmac_do_void_callback(__priv, mac, pcs_rane, __priv, __args) #define stmmac_pcs_get_adv_lp(__priv, __args...) \ stmmac_do_void_callback(__priv, mac, pcs_get_adv_lp, __args) #define stmmac_safety_feat_config(__priv, __args...) \ diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c index 542e2633a6f5..7008219fd88d 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c @@ -11,10 +11,10 @@ #include <linux/etherdevice.h> #include <linux/ethtool.h> #include <linux/interrupt.h> +#include <linux/io.h> #include <linux/mii.h> #include <linux/phylink.h> #include <linux/net_tstamp.h> -#include <asm/io.h> #include "stmmac.h" #include "dwmac_dma.h" @@ -1199,7 +1199,7 @@ static int stmmac_set_channels(struct net_device *dev, } static int stmmac_get_ts_info(struct net_device *dev, - struct ethtool_ts_info *info) + struct kernel_ethtool_ts_info *info) { struct stmmac_priv *priv = netdev_priv(dev); diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index c58782c41417..4b6a359e5a94 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -471,13 +471,6 @@ bool stmmac_eee_init(struct stmmac_priv *priv) { int eee_tw_timer = priv->eee_tw_timer; - /* Using PCS we cannot dial with the phy registers at this stage - * so we do not support extra feature like EEE. - */ - if (priv->hw->pcs == STMMAC_PCS_TBI || - priv->hw->pcs == STMMAC_PCS_RTBI) - return false; - /* Check if MAC core supports the EEE feature. */ if (!priv->dma_cap.eee) return false; @@ -956,11 +949,15 @@ static struct phylink_pcs *stmmac_mac_select_pcs(struct phylink_config *config, phy_interface_t interface) { struct stmmac_priv *priv = netdev_priv(to_net_dev(config->dev)); + struct phylink_pcs *pcs; - if (priv->hw->xpcs) - return &priv->hw->xpcs->pcs; + if (priv->plat->select_pcs) { + pcs = priv->plat->select_pcs(priv, interface); + if (!IS_ERR(pcs)) + return pcs; + } - return priv->hw->phylink_pcs; + return NULL; } static void stmmac_mac_config(struct phylink_config *config, unsigned int mode, @@ -1228,8 +1225,8 @@ static int stmmac_phy_setup(struct stmmac_priv *priv) mdio_bus_data = priv->plat->mdio_bus_data; if (mdio_bus_data) - priv->phylink_config.ovr_an_inband = - mdio_bus_data->xpcs_an_inband; + priv->phylink_config.default_an_inband = + mdio_bus_data->default_an_inband; /* Set the platform/firmware specified interface mode. Note, phylink * deals with the PHY interface mode, not the MAC interface mode. @@ -3953,9 +3950,7 @@ static int __stmmac_open(struct net_device *dev, if (ret < 0) return ret; - if (priv->hw->pcs != STMMAC_PCS_TBI && - priv->hw->pcs != STMMAC_PCS_RTBI && - (!priv->hw->xpcs || + if ((!priv->hw->xpcs || xpcs_get_an_mode(priv->hw->xpcs, mode) != DW_AN_C73)) { ret = stmmac_init_phy(dev); if (ret) { @@ -4097,8 +4092,6 @@ static int stmmac_release(struct net_device *dev) if (priv->plat->serdes_powerdown) priv->plat->serdes_powerdown(dev, priv->plat->bsp_priv); - netif_carrier_off(dev); - stmmac_release_ptp(priv); pm_runtime_put(priv->device); @@ -4244,18 +4237,32 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev) { struct dma_desc *desc, *first, *mss_desc = NULL; struct stmmac_priv *priv = netdev_priv(dev); - int nfrags = skb_shinfo(skb)->nr_frags; - u32 queue = skb_get_queue_mapping(skb); + int tmp_pay_len = 0, first_tx, nfrags; unsigned int first_entry, tx_packets; struct stmmac_txq_stats *txq_stats; - int tmp_pay_len = 0, first_tx; struct stmmac_tx_queue *tx_q; - bool has_vlan, set_ic; + u32 pay_len, mss, queue; u8 proto_hdr_len, hdr; - u32 pay_len, mss; dma_addr_t des; + bool set_ic; int i; + /* Always insert VLAN tag to SKB payload for TSO frames. + * + * Never insert VLAN tag by HW, since segments splited by + * TSO engine will be un-tagged by mistake. + */ + if (skb_vlan_tag_present(skb)) { + skb = __vlan_hwaccel_push_inside(skb); + if (unlikely(!skb)) { + priv->xstats.tx_dropped++; + return NETDEV_TX_OK; + } + } + + nfrags = skb_shinfo(skb)->nr_frags; + queue = skb_get_queue_mapping(skb); + tx_q = &priv->dma_conf.tx_queue[queue]; txq_stats = &priv->xstats.txq_stats[queue]; first_tx = tx_q->cur_tx; @@ -4308,9 +4315,6 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev) skb->data_len); } - /* Check if VLAN can be inserted by HW */ - has_vlan = stmmac_vlan_insert(priv, skb, tx_q); - first_entry = tx_q->cur_tx; WARN_ON(tx_q->tx_skbuff[first_entry]); @@ -4320,9 +4324,6 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev) desc = &tx_q->dma_tx[first_entry]; first = desc; - if (has_vlan) - stmmac_set_desc_vlan(priv, first, STMMAC_VLAN_INSERT); - /* first descriptor: fill Headers on Buf1 */ des = dma_map_single(priv->device, skb->data, skb_headlen(skb), DMA_TO_DEVICE); @@ -7690,8 +7691,6 @@ int stmmac_dvr_probe(struct device *device, ndev->features |= NETIF_F_RXHASH; ndev->vlan_features |= ndev->features; - /* TSO doesn't work on VLANs yet */ - ndev->vlan_features &= ~NETIF_F_TSO; /* MTU range: 46 - hw-specific max */ ndev->min_mtu = ETH_ZLEN - ETH_HLEN; @@ -7740,16 +7739,12 @@ int stmmac_dvr_probe(struct device *device, if (!pm_runtime_enabled(device)) pm_runtime_enable(device); - if (priv->hw->pcs != STMMAC_PCS_TBI && - priv->hw->pcs != STMMAC_PCS_RTBI) { - /* MDIO bus Registration */ - ret = stmmac_mdio_register(ndev); - if (ret < 0) { - dev_err_probe(priv->device, ret, - "%s: MDIO bus (id: %d) registration failed\n", - __func__, priv->plat->bus_id); - goto error_mdio_register; - } + ret = stmmac_mdio_register(ndev); + if (ret < 0) { + dev_err_probe(priv->device, ret, + "MDIO bus (id: %d) registration failed\n", + priv->plat->bus_id); + goto error_mdio_register; } if (priv->plat->speed_mode_2500) @@ -7791,9 +7786,7 @@ error_netdev_register: error_phy_setup: stmmac_pcs_clean(ndev); error_pcs_setup: - if (priv->hw->pcs != STMMAC_PCS_TBI && - priv->hw->pcs != STMMAC_PCS_RTBI) - stmmac_mdio_unregister(ndev); + stmmac_mdio_unregister(ndev); error_mdio_register: stmmac_napi_del(ndev); error_hw_init: @@ -7822,7 +7815,6 @@ void stmmac_dvr_remove(struct device *dev) stmmac_stop_all_dma(priv); stmmac_mac_set(priv, priv->ioaddr, false); - netif_carrier_off(ndev); unregister_netdev(ndev); #ifdef CONFIG_DEBUG_FS @@ -7834,10 +7826,8 @@ void stmmac_dvr_remove(struct device *dev) reset_control_assert(priv->plat->stmmac_ahb_rst); stmmac_pcs_clean(ndev); + stmmac_mdio_unregister(ndev); - if (priv->hw->pcs != STMMAC_PCS_TBI && - priv->hw->pcs != STMMAC_PCS_RTBI) - stmmac_mdio_unregister(ndev); destroy_workqueue(priv->wq); mutex_destroy(&priv->lock); bitmap_free(priv->af_xdp_zc_qps); diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c index aa43117134d3..03f90676b3ad 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c @@ -497,35 +497,33 @@ int stmmac_mdio_reset(struct mii_bus *bus) int stmmac_pcs_setup(struct net_device *ndev) { + struct fwnode_handle *devnode, *pcsnode; struct dw_xpcs *xpcs = NULL; struct stmmac_priv *priv; - int ret = -ENODEV; - int mode, addr; + int addr, mode, ret; priv = netdev_priv(ndev); mode = priv->plat->phy_interface; + devnode = priv->plat->port_node; if (priv->plat->pcs_init) { ret = priv->plat->pcs_init(priv); + } else if (fwnode_property_present(devnode, "pcs-handle")) { + pcsnode = fwnode_find_reference(devnode, "pcs-handle", 0); + xpcs = xpcs_create_fwnode(pcsnode, mode); + fwnode_handle_put(pcsnode); + ret = PTR_ERR_OR_ZERO(xpcs); } else if (priv->plat->mdio_bus_data && - priv->plat->mdio_bus_data->has_xpcs) { - /* Try to probe the XPCS by scanning all addresses */ - for (addr = 0; addr < PHY_MAX_ADDR; addr++) { - xpcs = xpcs_create_mdiodev(priv->mii, addr, mode); - if (IS_ERR(xpcs)) - continue; - - ret = 0; - break; - } + priv->plat->mdio_bus_data->pcs_mask) { + addr = ffs(priv->plat->mdio_bus_data->pcs_mask) - 1; + xpcs = xpcs_create_mdiodev(priv->mii, addr, mode); + ret = PTR_ERR_OR_ZERO(xpcs); } else { return 0; } - if (ret) { - dev_warn(priv->device, "No xPCS found\n"); - return ret; - } + if (ret) + return dev_err_probe(priv->device, ret, "No xPCS found\n"); priv->hw->xpcs = xpcs; @@ -610,7 +608,7 @@ int stmmac_mdio_register(struct net_device *ndev) snprintf(new_bus->id, MII_BUS_ID_SIZE, "%s-%x", new_bus->name, priv->plat->bus_id); new_bus->priv = ndev; - new_bus->phy_mask = mdio_bus_data->phy_mask; + new_bus->phy_mask = mdio_bus_data->phy_mask | mdio_bus_data->pcs_mask; new_bus->parent = priv->device; err = of_mdiobus_register(new_bus, mdio_node); diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pcs.h b/drivers/net/ethernet/stmicro/stmmac/stmmac_pcs.h index 13a30e6df4c1..1bdf87b237c4 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pcs.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pcs.h @@ -75,23 +75,6 @@ static inline void dwmac_pcs_isr(void __iomem *ioaddr, u32 reg, } /** - * dwmac_rane - To restart ANE - * @ioaddr: IO registers pointer - * @reg: Base address of the AN Control Register. - * @restart: to restart ANE - * Description: this is to just restart the Auto-Negotiation. - */ -static inline void dwmac_rane(void __iomem *ioaddr, u32 reg, bool restart) -{ - u32 value = readl(ioaddr + GMAC_AN_CTRL(reg)); - - if (restart) - value |= GMAC_AN_CTRL_RAN; - - writel(value, ioaddr + GMAC_AN_CTRL(reg)); -} - -/** * dwmac_ctrl_ane - To program the AN Control Register. * @ioaddr: IO registers pointer * @reg: Base address of the AN Control Register. diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c index 54797edc9b38..ad868e8d195d 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c @@ -764,8 +764,8 @@ EXPORT_SYMBOL_GPL(stmmac_get_platform_resources); * Description: Call the platform's init callback (if any) and propagate * the return value. */ -int stmmac_pltfr_init(struct platform_device *pdev, - struct plat_stmmacenet_data *plat) +static int stmmac_pltfr_init(struct platform_device *pdev, + struct plat_stmmacenet_data *plat) { int ret = 0; @@ -774,7 +774,6 @@ int stmmac_pltfr_init(struct platform_device *pdev, return ret; } -EXPORT_SYMBOL_GPL(stmmac_pltfr_init); /** * stmmac_pltfr_exit @@ -782,13 +781,12 @@ EXPORT_SYMBOL_GPL(stmmac_pltfr_init); * @plat: driver data platform structure * Description: Call the platform's exit callback (if any). */ -void stmmac_pltfr_exit(struct platform_device *pdev, - struct plat_stmmacenet_data *plat) +static void stmmac_pltfr_exit(struct platform_device *pdev, + struct plat_stmmacenet_data *plat) { if (plat->exit) plat->exit(pdev, plat->bsp_priv); } -EXPORT_SYMBOL_GPL(stmmac_pltfr_exit); /** * stmmac_pltfr_probe diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h index bb6fc7e59aed..72dc1a32e46d 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h @@ -17,11 +17,6 @@ devm_stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac); int stmmac_get_platform_resources(struct platform_device *pdev, struct stmmac_resources *stmmac_res); -int stmmac_pltfr_init(struct platform_device *pdev, - struct plat_stmmacenet_data *plat); -void stmmac_pltfr_exit(struct platform_device *pdev, - struct plat_stmmacenet_data *plat); - int stmmac_pltfr_probe(struct platform_device *pdev, struct plat_stmmacenet_data *plat, struct stmmac_resources *res); |