mirror of
https://github.com/torvalds/linux.git
synced 2026-06-03 03:53:37 +02:00
Merge branch 'net-bcmgenet-revise-suspend-resume'
Doug Berger says: ==================== net: bcmgenet: revise suspend/resume This commit set updates the GENET driver to reduce the delay to resume the ethernet link when the Wake on Lan features are used. In addition, the encoding of hardware versioning and features is revised to avoid some redundancy and improve readability as well as remove a warning that occurred for the BCM7712 device which updated the device major version while maintaining compatibility with the driver. The assignment of hardware descriptor rings was modified to simplify programming and to allow support for the hardware RX_CLS_FLOW_DISC filter action. ==================== Link: https://patch.msgid.link/20250306192643.2383632-1-opendmb@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
a3cc3f424d
File diff suppressed because it is too large
Load Diff
|
|
@ -1,6 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2014-2024 Broadcom
|
||||
* Copyright (c) 2014-2025 Broadcom
|
||||
*/
|
||||
|
||||
#ifndef __BCMGENET_H__
|
||||
|
|
@ -18,6 +18,9 @@
|
|||
|
||||
#include "../unimac.h"
|
||||
|
||||
/* Maximum number of hardware queues, downsized if needed */
|
||||
#define GENET_MAX_MQ_CNT 4
|
||||
|
||||
/* total number of Buffer Descriptors, same for Rx/Tx */
|
||||
#define TOTAL_DESC 256
|
||||
|
||||
|
|
@ -271,6 +274,8 @@ struct bcmgenet_mib_counters {
|
|||
/* Only valid for GENETv3+ */
|
||||
#define UMAC_IRQ_MDIO_DONE (1 << 23)
|
||||
#define UMAC_IRQ_MDIO_ERROR (1 << 24)
|
||||
#define UMAC_IRQ_MDIO_EVENT (UMAC_IRQ_MDIO_DONE | \
|
||||
UMAC_IRQ_MDIO_ERROR)
|
||||
|
||||
/* INTRL2 instance 1 definitions */
|
||||
#define UMAC_IRQ1_TX_INTR_MASK 0xFFFF
|
||||
|
|
@ -476,6 +481,7 @@ enum bcmgenet_version {
|
|||
#define GENET_HAS_EXT (1 << 1)
|
||||
#define GENET_HAS_MDIO_INTR (1 << 2)
|
||||
#define GENET_HAS_MOCA_LINK_DET (1 << 3)
|
||||
#define GENET_HAS_EPHY_16NM (1 << 4)
|
||||
|
||||
/* BCMGENET hardware parameters, keep this structure nicely aligned
|
||||
* since it is going to be used in hot paths
|
||||
|
|
@ -496,7 +502,6 @@ struct bcmgenet_hw_params {
|
|||
u32 rdma_offset;
|
||||
u32 tdma_offset;
|
||||
u32 words_per_bd;
|
||||
u32 flags;
|
||||
};
|
||||
|
||||
struct bcmgenet_skb_cb {
|
||||
|
|
@ -513,7 +518,6 @@ struct bcmgenet_tx_ring {
|
|||
unsigned long packets;
|
||||
unsigned long bytes;
|
||||
unsigned int index; /* ring index */
|
||||
unsigned int queue; /* queue index */
|
||||
struct enet_cb *cbs; /* tx ring buffer control block*/
|
||||
unsigned int size; /* size of each tx ring */
|
||||
unsigned int clean_ptr; /* Tx ring clean pointer */
|
||||
|
|
@ -523,8 +527,6 @@ struct bcmgenet_tx_ring {
|
|||
unsigned int prod_index; /* Tx ring producer index SW copy */
|
||||
unsigned int cb_ptr; /* Tx ring initial CB ptr */
|
||||
unsigned int end_ptr; /* Tx ring end CB ptr */
|
||||
void (*int_enable)(struct bcmgenet_tx_ring *);
|
||||
void (*int_disable)(struct bcmgenet_tx_ring *);
|
||||
struct bcmgenet_priv *priv;
|
||||
};
|
||||
|
||||
|
|
@ -553,8 +555,6 @@ struct bcmgenet_rx_ring {
|
|||
struct bcmgenet_net_dim dim;
|
||||
u32 rx_max_coalesced_frames;
|
||||
u32 rx_coalesce_usecs;
|
||||
void (*int_enable)(struct bcmgenet_rx_ring *);
|
||||
void (*int_disable)(struct bcmgenet_rx_ring *);
|
||||
struct bcmgenet_priv *priv;
|
||||
};
|
||||
|
||||
|
|
@ -583,7 +583,7 @@ struct bcmgenet_priv {
|
|||
struct enet_cb *tx_cbs;
|
||||
unsigned int num_tx_bds;
|
||||
|
||||
struct bcmgenet_tx_ring tx_rings[DESC_INDEX + 1];
|
||||
struct bcmgenet_tx_ring tx_rings[GENET_MAX_MQ_CNT + 1];
|
||||
|
||||
/* receive variables */
|
||||
void __iomem *rx_bds;
|
||||
|
|
@ -593,10 +593,11 @@ struct bcmgenet_priv {
|
|||
struct bcmgenet_rxnfc_rule rxnfc_rules[MAX_NUM_OF_FS_RULES];
|
||||
struct list_head rxnfc_list;
|
||||
|
||||
struct bcmgenet_rx_ring rx_rings[DESC_INDEX + 1];
|
||||
struct bcmgenet_rx_ring rx_rings[GENET_MAX_MQ_CNT + 1];
|
||||
|
||||
/* other misc variables */
|
||||
struct bcmgenet_hw_params *hw_params;
|
||||
const struct bcmgenet_hw_params *hw_params;
|
||||
u32 flags;
|
||||
unsigned autoneg_pause:1;
|
||||
unsigned tx_pause:1;
|
||||
unsigned rx_pause:1;
|
||||
|
|
@ -615,7 +616,6 @@ struct bcmgenet_priv {
|
|||
phy_interface_t phy_interface;
|
||||
int phy_addr;
|
||||
int ext_phy;
|
||||
bool ephy_16nm;
|
||||
|
||||
/* Interrupt variables */
|
||||
struct work_struct bcmgenet_irq_work;
|
||||
|
|
@ -643,13 +643,37 @@ struct bcmgenet_priv {
|
|||
struct clk *clk_wol;
|
||||
u32 wolopts;
|
||||
u8 sopass[SOPASS_MAX];
|
||||
bool wol_active;
|
||||
|
||||
struct bcmgenet_mib_counters mib;
|
||||
|
||||
struct ethtool_keee eee;
|
||||
};
|
||||
|
||||
static inline bool bcmgenet_has_40bits(struct bcmgenet_priv *priv)
|
||||
{
|
||||
return !!(priv->flags & GENET_HAS_40BITS);
|
||||
}
|
||||
|
||||
static inline bool bcmgenet_has_ext(struct bcmgenet_priv *priv)
|
||||
{
|
||||
return !!(priv->flags & GENET_HAS_EXT);
|
||||
}
|
||||
|
||||
static inline bool bcmgenet_has_mdio_intr(struct bcmgenet_priv *priv)
|
||||
{
|
||||
return !!(priv->flags & GENET_HAS_MDIO_INTR);
|
||||
}
|
||||
|
||||
static inline bool bcmgenet_has_moca_link_det(struct bcmgenet_priv *priv)
|
||||
{
|
||||
return !!(priv->flags & GENET_HAS_MOCA_LINK_DET);
|
||||
}
|
||||
|
||||
static inline bool bcmgenet_has_ephy_16nm(struct bcmgenet_priv *priv)
|
||||
{
|
||||
return !!(priv->flags & GENET_HAS_EPHY_16NM);
|
||||
}
|
||||
|
||||
#define GENET_IO_MACRO(name, offset) \
|
||||
static inline u32 bcmgenet_##name##_readl(struct bcmgenet_priv *priv, \
|
||||
u32 off) \
|
||||
|
|
@ -702,8 +726,8 @@ void bcmgenet_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol);
|
|||
int bcmgenet_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol);
|
||||
int bcmgenet_wol_power_down_cfg(struct bcmgenet_priv *priv,
|
||||
enum bcmgenet_power_mode mode);
|
||||
void bcmgenet_wol_power_up_cfg(struct bcmgenet_priv *priv,
|
||||
enum bcmgenet_power_mode mode);
|
||||
int bcmgenet_wol_power_up_cfg(struct bcmgenet_priv *priv,
|
||||
enum bcmgenet_power_mode mode);
|
||||
|
||||
void bcmgenet_eee_enable_set(struct net_device *dev, bool enable,
|
||||
bool tx_lpi_enabled);
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
/*
|
||||
* Broadcom GENET (Gigabit Ethernet) Wake-on-LAN support
|
||||
*
|
||||
* Copyright (c) 2014-2024 Broadcom
|
||||
* Copyright (c) 2014-2025 Broadcom
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "bcmgenet_wol: " fmt
|
||||
|
|
@ -145,8 +145,7 @@ int bcmgenet_wol_power_down_cfg(struct bcmgenet_priv *priv,
|
|||
enum bcmgenet_power_mode mode)
|
||||
{
|
||||
struct net_device *dev = priv->dev;
|
||||
struct bcmgenet_rxnfc_rule *rule;
|
||||
u32 reg, hfb_ctrl_reg, hfb_enable = 0;
|
||||
u32 reg, hfb_ctrl_reg;
|
||||
int retries = 0;
|
||||
|
||||
if (mode != GENET_POWER_WOL_MAGIC) {
|
||||
|
|
@ -154,18 +153,6 @@ int bcmgenet_wol_power_down_cfg(struct bcmgenet_priv *priv,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Can't suspend with WoL if MAC is still in reset */
|
||||
spin_lock_bh(&priv->reg_lock);
|
||||
reg = bcmgenet_umac_readl(priv, UMAC_CMD);
|
||||
if (reg & CMD_SW_RESET)
|
||||
reg &= ~CMD_SW_RESET;
|
||||
|
||||
/* disable RX */
|
||||
reg &= ~CMD_RX_EN;
|
||||
bcmgenet_umac_writel(priv, reg, UMAC_CMD);
|
||||
spin_unlock_bh(&priv->reg_lock);
|
||||
mdelay(10);
|
||||
|
||||
if (priv->wolopts & (WAKE_MAGIC | WAKE_MAGICSECURE)) {
|
||||
reg = bcmgenet_umac_readl(priv, UMAC_MPD_CTRL);
|
||||
reg |= MPD_EN;
|
||||
|
|
@ -177,13 +164,8 @@ int bcmgenet_wol_power_down_cfg(struct bcmgenet_priv *priv,
|
|||
}
|
||||
|
||||
hfb_ctrl_reg = bcmgenet_hfb_reg_readl(priv, HFB_CTRL);
|
||||
if (priv->wolopts & WAKE_FILTER) {
|
||||
list_for_each_entry(rule, &priv->rxnfc_list, list)
|
||||
if (rule->fs.ring_cookie == RX_CLS_FLOW_WAKE)
|
||||
hfb_enable |= (1 << rule->fs.location);
|
||||
reg = (hfb_ctrl_reg & ~RBUF_HFB_EN) | RBUF_ACPI_EN;
|
||||
bcmgenet_hfb_reg_writel(priv, reg, HFB_CTRL);
|
||||
}
|
||||
reg = hfb_ctrl_reg | RBUF_ACPI_EN;
|
||||
bcmgenet_hfb_reg_writel(priv, reg, HFB_CTRL);
|
||||
|
||||
/* Do not leave UniMAC in MPD mode only */
|
||||
retries = bcmgenet_poll_wol_status(priv);
|
||||
|
|
@ -198,15 +180,12 @@ int bcmgenet_wol_power_down_cfg(struct bcmgenet_priv *priv,
|
|||
netif_dbg(priv, wol, dev, "MPD WOL-ready status set after %d msec\n",
|
||||
retries);
|
||||
|
||||
clk_prepare_enable(priv->clk_wol);
|
||||
priv->wol_active = 1;
|
||||
/* Disable phy status updates while suspending */
|
||||
mutex_lock(&dev->phydev->lock);
|
||||
dev->phydev->state = PHY_READY;
|
||||
mutex_unlock(&dev->phydev->lock);
|
||||
|
||||
if (hfb_enable) {
|
||||
bcmgenet_hfb_reg_writel(priv, hfb_enable,
|
||||
HFB_FLT_ENABLE_V3PLUS + 4);
|
||||
hfb_ctrl_reg = RBUF_HFB_EN | RBUF_ACPI_EN;
|
||||
bcmgenet_hfb_reg_writel(priv, hfb_ctrl_reg, HFB_CTRL);
|
||||
}
|
||||
clk_prepare_enable(priv->clk_wol);
|
||||
|
||||
/* Enable CRC forward */
|
||||
spin_lock_bh(&priv->reg_lock);
|
||||
|
|
@ -214,13 +193,17 @@ int bcmgenet_wol_power_down_cfg(struct bcmgenet_priv *priv,
|
|||
priv->crc_fwd_en = 1;
|
||||
reg |= CMD_CRC_FWD;
|
||||
|
||||
/* Can't suspend with WoL if MAC is still in reset */
|
||||
if (reg & CMD_SW_RESET)
|
||||
reg &= ~CMD_SW_RESET;
|
||||
|
||||
/* Receiver must be enabled for WOL MP detection */
|
||||
reg |= CMD_RX_EN;
|
||||
bcmgenet_umac_writel(priv, reg, UMAC_CMD);
|
||||
spin_unlock_bh(&priv->reg_lock);
|
||||
|
||||
reg = UMAC_IRQ_MPD_R;
|
||||
if (hfb_enable)
|
||||
if (hfb_ctrl_reg & RBUF_HFB_EN)
|
||||
reg |= UMAC_IRQ_HFB_SM | UMAC_IRQ_HFB_MM;
|
||||
|
||||
bcmgenet_intrl2_0_writel(priv, reg, INTRL2_CPU_MASK_CLEAR);
|
||||
|
|
@ -228,40 +211,42 @@ int bcmgenet_wol_power_down_cfg(struct bcmgenet_priv *priv,
|
|||
return 0;
|
||||
}
|
||||
|
||||
void bcmgenet_wol_power_up_cfg(struct bcmgenet_priv *priv,
|
||||
enum bcmgenet_power_mode mode)
|
||||
int bcmgenet_wol_power_up_cfg(struct bcmgenet_priv *priv,
|
||||
enum bcmgenet_power_mode mode)
|
||||
{
|
||||
struct net_device *dev = priv->dev;
|
||||
u32 reg;
|
||||
|
||||
if (mode != GENET_POWER_WOL_MAGIC) {
|
||||
netif_err(priv, wol, priv->dev, "invalid mode: %d\n", mode);
|
||||
return;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!priv->wol_active)
|
||||
return; /* failed to suspend so skip the rest */
|
||||
|
||||
priv->wol_active = 0;
|
||||
clk_disable_unprepare(priv->clk_wol);
|
||||
priv->crc_fwd_en = 0;
|
||||
|
||||
bcmgenet_intrl2_0_writel(priv, UMAC_IRQ_WAKE_EVENT,
|
||||
INTRL2_CPU_MASK_SET);
|
||||
if (bcmgenet_has_mdio_intr(priv))
|
||||
bcmgenet_intrl2_0_writel(priv,
|
||||
UMAC_IRQ_MDIO_EVENT,
|
||||
INTRL2_CPU_MASK_CLEAR);
|
||||
|
||||
/* Disable Magic Packet Detection */
|
||||
if (priv->wolopts & (WAKE_MAGIC | WAKE_MAGICSECURE)) {
|
||||
reg = bcmgenet_umac_readl(priv, UMAC_MPD_CTRL);
|
||||
if (!(reg & MPD_EN))
|
||||
return; /* already reset so skip the rest */
|
||||
return -EPERM; /* already reset so skip the rest */
|
||||
reg &= ~(MPD_EN | MPD_PW_EN);
|
||||
bcmgenet_umac_writel(priv, reg, UMAC_MPD_CTRL);
|
||||
}
|
||||
|
||||
/* Disable WAKE_FILTER Detection */
|
||||
if (priv->wolopts & WAKE_FILTER) {
|
||||
reg = bcmgenet_hfb_reg_readl(priv, HFB_CTRL);
|
||||
if (!(reg & RBUF_ACPI_EN))
|
||||
return; /* already reset so skip the rest */
|
||||
reg &= ~(RBUF_HFB_EN | RBUF_ACPI_EN);
|
||||
bcmgenet_hfb_reg_writel(priv, reg, HFB_CTRL);
|
||||
}
|
||||
/* Disable ACPI mode */
|
||||
reg = bcmgenet_hfb_reg_readl(priv, HFB_CTRL);
|
||||
if (!(reg & RBUF_ACPI_EN))
|
||||
return -EPERM; /* already reset so skip the rest */
|
||||
reg &= ~RBUF_ACPI_EN;
|
||||
bcmgenet_hfb_reg_writel(priv, reg, HFB_CTRL);
|
||||
|
||||
/* Disable CRC Forward */
|
||||
spin_lock_bh(&priv->reg_lock);
|
||||
|
|
@ -269,4 +254,14 @@ void bcmgenet_wol_power_up_cfg(struct bcmgenet_priv *priv,
|
|||
reg &= ~CMD_CRC_FWD;
|
||||
bcmgenet_umac_writel(priv, reg, UMAC_CMD);
|
||||
spin_unlock_bh(&priv->reg_lock);
|
||||
|
||||
/* Resume link status tracking */
|
||||
mutex_lock(&dev->phydev->lock);
|
||||
if (dev->phydev->link)
|
||||
dev->phydev->state = PHY_RUNNING;
|
||||
else
|
||||
dev->phydev->state = PHY_NOLINK;
|
||||
mutex_unlock(&dev->phydev->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
/*
|
||||
* Broadcom GENET MDIO routines
|
||||
*
|
||||
* Copyright (c) 2014-2024 Broadcom
|
||||
* Copyright (c) 2014-2025 Broadcom
|
||||
*/
|
||||
|
||||
#include <linux/acpi.h>
|
||||
|
|
@ -154,7 +154,7 @@ void bcmgenet_phy_power_set(struct net_device *dev, bool enable)
|
|||
u32 reg = 0;
|
||||
|
||||
/* EXT_GPHY_CTRL is only valid for GENETv4 and onward */
|
||||
if (GENET_IS_V4(priv) || priv->ephy_16nm) {
|
||||
if (GENET_IS_V4(priv) || bcmgenet_has_ephy_16nm(priv)) {
|
||||
reg = bcmgenet_ext_readl(priv, EXT_GPHY_CTRL);
|
||||
if (enable) {
|
||||
reg &= ~EXT_CK25_DIS;
|
||||
|
|
@ -184,7 +184,7 @@ void bcmgenet_phy_power_set(struct net_device *dev, bool enable)
|
|||
|
||||
static void bcmgenet_moca_phy_setup(struct bcmgenet_priv *priv)
|
||||
{
|
||||
if (priv->hw_params->flags & GENET_HAS_MOCA_LINK_DET)
|
||||
if (bcmgenet_has_moca_link_det(priv))
|
||||
fixed_phy_set_link_update(priv->dev->phydev,
|
||||
bcmgenet_fixed_phy_link_update);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user