summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/freescale
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-08-27 13:53:43 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2026-08-27 13:53:43 -0700
commit1b78070aaef63512688aebfbc82365ef9d6660f1 (patch)
tree691c0aeaa3d92278ceeb6ace56bc8cd56a7f2ae8 /drivers/net/ethernet/freescale
parent3ba13f5e7180c034b0a1ef7e052fb780856b134e (diff)
parent4a9d62a8774f130a5b8de26ca9f415e6050a9d51 (diff)
Merge tag 'net-7.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/netHEADmaster
Pull networking fixes from Jakub Kicinski: "Including fixes from Bluetooth, IPSec and Netfilter. Current release - fix to a fix: - netfilter: ipset: remove need to allocate memory on delete operations Current release - regressions: - macb: drop CONFIG_OF #if block, fix build Previous releases - always broken: - stream of fixes for SCTP continues - inet: frags: strip GSO state from fragments before reassembly - virtio-net: ensure that TCP packets don't overflow gso_segs - tcp-ao: fix use-after-free of current_key on reconnect to another peer - page_pool: remove zone/policy GFP flags when allocating XArray entries - Bluetooth: L2CAP: reject accept queue add unless BT_LISTEN - tls: device: fix out-of-bounds write in tls_append_frag() - eth: bnxt: - ring the doorbell when SW USO exits early, avoid packets stuck in Tx - gate TPH enablement behind BNXT_SUPPORTS_QUEUE_API check, avoid users of older NICs seeing non-actionable warning messages - eth: qede: fix NULL pointer dereference in TPA fragment processing" * tag 'net-7.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net: (216 commits) inet: frags: strip GSO state from fragments before reassembly net/sched: sch_htb: limit htb_classify inner-class filter hops selftests/net: packetdrill: add tcp_urg_ptr_retransmit tcp: fix corruption of urgent data on multi-segment retransmit usb: atm: usbatm: fix invalid ci_range initialization net: fec: only stop PTP if it was initialized slip: remove slip_hangup() to fix use-after-free in slip_receive_buf() net: bridge: mcast: fix use-after-free of a master VLAN's multicast context net/sched: bound qdisc_pkt_len to prevent qdisc soft lockup net: dsa: mxl862xx: enable assisted learning on CPU port net: stmmac: restore NET_IP_ALIGN in the RX DMA offset net: stmmac: drop gso_enabled_types and rely on netdev features net: stmmac: selftests: Don't test flow control for small rx fifos net: stmmac: selftests: Account for the UC filter list for filtering tests net: stmmac: dwxgmac: Account for the primary MAC address for UC filtering net: stmmac: dwmac4: Account for the primary MAC address for UC filtering net: stmmac: dwmac1000: Account for the primary MAC address for UC filtering net: stmmac: selftests: Check multiple MMC counters selftests: net: Fix slow configurations in big_tcp_tunnels.sh selftests: net: Lower threshold with csum offload off in big_tcp_tunnels.sh ...
Diffstat (limited to 'drivers/net/ethernet/freescale')
-rw-r--r--drivers/net/ethernet/freescale/enetc/enetc.c72
-rw-r--r--drivers/net/ethernet/freescale/enetc/enetc.h9
-rw-r--r--drivers/net/ethernet/freescale/enetc/enetc4_pf.c16
-rw-r--r--drivers/net/ethernet/freescale/enetc/enetc_pf.c14
-rw-r--r--drivers/net/ethernet/freescale/fec_main.c6
5 files changed, 76 insertions, 41 deletions
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c
index 8e3f345dd9aa..80f0082f6c63 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -81,6 +81,33 @@ void enetc_reset_mac_addr_filter(struct enetc_mac_filter *filter)
}
EXPORT_SYMBOL_GPL(enetc_reset_mac_addr_filter);
+void enetc_set_congestion_mode(struct enetc_ndev_priv *priv, bool enable)
+{
+ struct enetc_si *si = priv->si;
+ struct enetc_hw *hw = &si->hw;
+
+ spin_lock(&si->gen_lock);
+
+ if (enable)
+ set_bit(ENETC_RXBDR_CM, &priv->flags);
+ else
+ clear_bit(ENETC_RXBDR_CM, &priv->flags);
+
+ for (int i = 0; i < priv->num_rx_rings; i++) {
+ u32 old_rbmr = enetc_rxbdr_rd(hw, i, ENETC_RBMR);
+ u32 rbmr;
+
+ rbmr = u32_replace_bits(old_rbmr, enable, ENETC_RBMR_CM);
+ if (rbmr == old_rbmr)
+ continue;
+
+ enetc_rxbdr_wr(hw, i, ENETC_RBMR, rbmr);
+ }
+
+ spin_unlock(&si->gen_lock);
+}
+EXPORT_SYMBOL_GPL(enetc_set_congestion_mode);
+
static int enetc_num_stack_tx_queues(struct enetc_ndev_priv *priv)
{
int num_tx_rings = priv->num_tx_rings;
@@ -2632,7 +2659,6 @@ static void enetc_setup_rxbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring,
bool extended)
{
int idx = rx_ring->index;
- u32 rbmr = 0;
enetc_rxbdr_wr(hw, idx, ENETC_RBBAR0,
lower_32_bits(rx_ring->bd_dma_base));
@@ -2660,12 +2686,6 @@ static void enetc_setup_rxbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring,
enetc_rxbdr_wr(hw, idx, ENETC_RBICR0, ENETC_RBICR0_ICEN | 0x1);
rx_ring->ext_en = extended;
- if (rx_ring->ext_en)
- rbmr |= ENETC_RBMR_BDS;
-
- if (rx_ring->ndev->features & NETIF_F_HW_VLAN_CTAG_RX)
- rbmr |= ENETC_RBMR_VTE;
-
rx_ring->rcir = hw->reg + ENETC_BDR(RX, idx, ENETC_RBCIR);
rx_ring->idr = hw->reg + ENETC_SIRXIDR;
@@ -2676,8 +2696,6 @@ static void enetc_setup_rxbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring,
enetc_lock_mdio();
enetc_refill_rx_ring(rx_ring, enetc_bd_unused(rx_ring));
enetc_unlock_mdio();
-
- enetc_rxbdr_wr(hw, idx, ENETC_RBMR, rbmr);
}
static void enetc_setup_bdrs(struct enetc_ndev_priv *priv, bool extended)
@@ -2704,21 +2722,34 @@ static void enetc_enable_txbdr(struct enetc_hw *hw, struct enetc_bdr *tx_ring)
static void enetc_enable_rxbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring)
{
+ struct enetc_ndev_priv *priv = netdev_priv(rx_ring->ndev);
int idx = rx_ring->index;
- u32 rbmr;
+ u32 rbmr = ENETC_RBMR_EN;
+
+ if (rx_ring->ext_en)
+ rbmr |= ENETC_RBMR_BDS;
+
+ if (rx_ring->ndev->features & NETIF_F_HW_VLAN_CTAG_RX)
+ rbmr |= ENETC_RBMR_VTE;
+
+ if (test_bit(ENETC_RXBDR_CM, &priv->flags))
+ rbmr |= ENETC_RBMR_CM;
- rbmr = enetc_rxbdr_rd(hw, idx, ENETC_RBMR);
- rbmr |= ENETC_RBMR_EN;
enetc_rxbdr_wr(hw, idx, ENETC_RBMR, rbmr);
}
static void enetc_enable_rx_bdrs(struct enetc_ndev_priv *priv)
{
- struct enetc_hw *hw = &priv->si->hw;
+ struct enetc_si *si = priv->si;
+ struct enetc_hw *hw = &si->hw;
int i;
+ spin_lock(&si->gen_lock);
+
for (i = 0; i < priv->num_rx_rings; i++)
enetc_enable_rxbdr(hw, priv->rx_ring[i]);
+
+ spin_unlock(&si->gen_lock);
}
static void enetc_enable_tx_bdrs(struct enetc_ndev_priv *priv)
@@ -2748,11 +2779,16 @@ static void enetc_disable_txbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring)
static void enetc_disable_rx_bdrs(struct enetc_ndev_priv *priv)
{
- struct enetc_hw *hw = &priv->si->hw;
+ struct enetc_si *si = priv->si;
+ struct enetc_hw *hw = &si->hw;
int i;
+ spin_lock(&si->gen_lock);
+
for (i = 0; i < priv->num_rx_rings; i++)
enetc_disable_rxbdr(hw, priv->rx_ring[i]);
+
+ spin_unlock(&si->gen_lock);
}
static void enetc_disable_tx_bdrs(struct enetc_ndev_priv *priv)
@@ -3344,11 +3380,16 @@ EXPORT_SYMBOL_GPL(enetc_get_stats);
static void enetc_enable_rxvlan(struct net_device *ndev, bool en)
{
struct enetc_ndev_priv *priv = netdev_priv(ndev);
- struct enetc_hw *hw = &priv->si->hw;
+ struct enetc_si *si = priv->si;
+ struct enetc_hw *hw = &si->hw;
int i;
+ spin_lock(&si->gen_lock);
+
for (i = 0; i < priv->num_rx_rings; i++)
enetc_bdr_enable_rxvlan(hw, i, en);
+
+ spin_unlock(&si->gen_lock);
}
static void enetc_enable_txvlan(struct net_device *ndev, bool en)
@@ -3679,6 +3720,7 @@ int enetc_pci_probe(struct pci_dev *pdev, const char *name, int sizeof_priv)
si = PTR_ALIGN(p, ENETC_SI_ALIGN);
si->pad = (char *)si - (char *)p;
+ spin_lock_init(&si->gen_lock);
pci_set_drvdata(pdev, si);
si->pdev = pdev;
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h b/drivers/net/ethernet/freescale/enetc/enetc.h
index 8839cfb49bcf..d1e9d9130057 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -309,6 +309,13 @@ struct enetc_si {
struct net_device *ndev; /* back ref. */
+ /* General-purpose lock serializing updates that must not race,
+ * e.g. read-modify-write of shared hardware registers and of
+ * selected priv->flags bits between the phylink link callbacks
+ * and the ring (re)configuration path.
+ */
+ spinlock_t gen_lock;
+
union {
struct enetc_cbdr cbd_ring; /* Only ENETC 1.0 */
struct ntmp_user ntmp_user; /* ENETC 4.1 and later */
@@ -417,6 +424,7 @@ enum enetc_active_offloads {
enum enetc_flags_bit {
ENETC_TX_ONESTEP_TSTAMP_IN_PROGRESS = 0,
ENETC_TX_DOWN,
+ ENETC_RXBDR_CM,
};
/* interrupt coalescing modes */
@@ -505,6 +513,7 @@ int enetc_get_driver_data(struct enetc_si *si);
void enetc_add_mac_addr_ht_filter(struct enetc_mac_filter *filter,
const unsigned char *addr);
void enetc_reset_mac_addr_filter(struct enetc_mac_filter *filter);
+void enetc_set_congestion_mode(struct enetc_ndev_priv *priv, bool enable);
int enetc_open(struct net_device *ndev);
int enetc_close(struct net_device *ndev);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
index fcfbabb29d22..9bb1004548ab 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c
@@ -718,22 +718,14 @@ static void enetc4_set_rx_pause(struct enetc_pf *pf, bool rx_pause)
enetc_port_mac_wr(si, ENETC4_PM_CMD_CFG(0), val);
}
-static void enetc4_set_tx_pause(struct enetc_pf *pf, int num_rxbdr, bool tx_pause)
+static void enetc4_set_tx_pause(struct enetc_pf *pf, bool tx_pause)
{
+ struct enetc_ndev_priv *priv = netdev_priv(pf->si->ndev);
u32 pause_off_thresh = 0, pause_on_thresh = 0;
u32 init_quanta = 0, refresh_quanta = 0;
struct enetc_hw *hw = &pf->si->hw;
- u32 rbmr, old_rbmr;
- int i;
- for (i = 0; i < num_rxbdr; i++) {
- old_rbmr = enetc_rxbdr_rd(hw, i, ENETC_RBMR);
- rbmr = u32_replace_bits(old_rbmr, tx_pause ? 1 : 0, ENETC_RBMR_CM);
- if (rbmr == old_rbmr)
- continue;
-
- enetc_rxbdr_wr(hw, i, ENETC_RBMR, rbmr);
- }
+ enetc_set_congestion_mode(priv, tx_pause);
if (tx_pause) {
/* When the port first enters congestion, send a PAUSE request
@@ -898,7 +890,7 @@ static void enetc4_pl_mac_link_up(struct phylink_config *config,
tx_pause = false;
}
- enetc4_set_tx_pause(pf, priv->num_rx_rings, tx_pause);
+ enetc4_set_tx_pause(pf, tx_pause);
enetc4_set_rx_pause(pf, rx_pause);
enetc4_mac_tx_enable(pf);
enetc4_mac_rx_enable(pf);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index a509929f89f2..55c07c528f22 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -556,8 +556,7 @@ static void enetc_pl_mac_link_up(struct phylink_config *config,
struct enetc_hw *hw = &pf->si->hw;
struct enetc_si *si = pf->si;
struct enetc_ndev_priv *priv;
- u32 rbmr, cmd_cfg;
- int idx;
+ u32 cmd_cfg;
priv = netdev_priv(pf->si->ndev);
@@ -569,16 +568,7 @@ static void enetc_pl_mac_link_up(struct phylink_config *config,
enetc_force_rgmii_mac(si, speed, duplex);
/* Flow control */
- for (idx = 0; idx < priv->num_rx_rings; idx++) {
- rbmr = enetc_rxbdr_rd(hw, idx, ENETC_RBMR);
-
- if (tx_pause)
- rbmr |= ENETC_RBMR_CM;
- else
- rbmr &= ~ENETC_RBMR_CM;
-
- enetc_rxbdr_wr(hw, idx, ENETC_RBMR, rbmr);
- }
+ enetc_set_congestion_mode(priv, tx_pause);
if (tx_pause) {
/* When the port first enters congestion, send a PAUSE request
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index ced4dbf8cd90..794ec427b0ee 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -5457,7 +5457,8 @@ failed_mii_init:
failed_irq:
fec_enet_deinit(ndev);
failed_init:
- fec_ptp_stop(pdev);
+ if (fep->bufdesc_ex)
+ fec_ptp_stop(pdev);
failed_reset:
pm_runtime_put_noidle(&pdev->dev);
pm_runtime_disable(&pdev->dev);
@@ -5499,7 +5500,8 @@ fec_drv_remove(struct platform_device *pdev)
ERR_PTR(ret));
cancel_work_sync(&fep->tx_timeout_work);
- fec_ptp_stop(pdev);
+ if (fep->bufdesc_ex)
+ fec_ptp_stop(pdev);
unregister_netdev(ndev);
fec_enet_mii_remove(fep);
if (fep->reg_phy)