From: Linus Walleij <linusw@kernel.org>
To: "Hans Ulli Kroll" <ulli.kroll@googlemail.com>,
"Andrew Lunn" <andrew+netdev@lunn.ch>,
"David S. Miller" <davem@davemloft.net>,
"Eric Dumazet" <edumazet@google.com>,
"Jakub Kicinski" <kuba@kernel.org>,
"Paolo Abeni" <pabeni@redhat.com>,
"Michał Mirosław" <mirq-linux@rere.qmqm.pl>,
"Myeonghun Pak" <mhun512@gmail.com>
Cc: netdev@vger.kernel.org, Linus Walleij <linusw@kernel.org>
Subject: [PATCH net-next v2 11/11] net: ethernet: cortina: Use guard helpers for locking
Date: Mon, 28 Sep 2026 10:50:37 +0200 [thread overview]
Message-ID: <20260928-gemini-ethernet-fixes-3-v2-11-758a795d7a78@kernel.org> (raw)
In-Reply-To: <20260928-gemini-ethernet-fixes-3-v2-0-758a795d7a78@kernel.org>
Use cleanup guard helpers to scope the driver's spinlocks
automatically.
Assisted-by: LLM
Signed-off-by: Linus Walleij <linusw@kernel.org>
---
drivers/net/ethernet/cortina/gemini.c | 144 +++++++++++++---------------------
1 file changed, 53 insertions(+), 91 deletions(-)
diff --git a/drivers/net/ethernet/cortina/gemini.c b/drivers/net/ethernet/cortina/gemini.c
index 910de9925949..4fdd7478601f 100644
--- a/drivers/net/ethernet/cortina/gemini.c
+++ b/drivers/net/ethernet/cortina/gemini.c
@@ -24,6 +24,7 @@
#include <linux/slab.h>
#include <linux/dma-mapping.h>
#include <linux/cache.h>
+#include <linux/cleanup.h>
#include <linux/interrupt.h>
#include <linux/reset.h>
#include <linux/clk.h>
@@ -240,46 +241,37 @@ static void gmac_update_config0_reg(struct net_device *netdev,
u32 val, u32 vmask)
{
struct gemini_ethernet_port *port = netdev_priv(netdev);
- unsigned long flags;
u32 reg;
- spin_lock_irqsave(&port->config_lock, flags);
+ guard(spinlock_irqsave)(&port->config_lock);
reg = readl(port->gmac_base + GMAC_CONFIG0);
reg = (reg & ~vmask) | val;
writel(reg, port->gmac_base + GMAC_CONFIG0);
-
- spin_unlock_irqrestore(&port->config_lock, flags);
}
static void gmac_enable_tx_rx(struct net_device *netdev)
{
struct gemini_ethernet_port *port = netdev_priv(netdev);
- unsigned long flags;
u32 reg;
- spin_lock_irqsave(&port->config_lock, flags);
+ guard(spinlock_irqsave)(&port->config_lock);
reg = readl(port->gmac_base + GMAC_CONFIG0);
reg &= ~CONFIG0_TX_RX_DISABLE;
writel(reg, port->gmac_base + GMAC_CONFIG0);
-
- spin_unlock_irqrestore(&port->config_lock, flags);
}
static void gmac_disable_tx_rx(struct net_device *netdev)
{
struct gemini_ethernet_port *port = netdev_priv(netdev);
- unsigned long flags;
u32 val;
- spin_lock_irqsave(&port->config_lock, flags);
-
- val = readl(port->gmac_base + GMAC_CONFIG0);
- val |= CONFIG0_TX_RX_DISABLE;
- writel(val, port->gmac_base + GMAC_CONFIG0);
-
- spin_unlock_irqrestore(&port->config_lock, flags);
+ scoped_guard(spinlock_irqsave, &port->config_lock) {
+ val = readl(port->gmac_base + GMAC_CONFIG0);
+ val |= CONFIG0_TX_RX_DISABLE;
+ writel(val, port->gmac_base + GMAC_CONFIG0);
+ }
mdelay(10); /* let GMAC consume packet */
}
@@ -287,10 +279,9 @@ static void gmac_disable_tx_rx(struct net_device *netdev)
static void gmac_set_flow_control(struct net_device *netdev, bool tx, bool rx)
{
struct gemini_ethernet_port *port = netdev_priv(netdev);
- unsigned long flags;
u32 val;
- spin_lock_irqsave(&port->config_lock, flags);
+ guard(spinlock_irqsave)(&port->config_lock);
val = readl(port->gmac_base + GMAC_CONFIG0);
val &= ~CONFIG0_FLOW_CTL;
@@ -299,8 +290,6 @@ static void gmac_set_flow_control(struct net_device *netdev, bool tx, bool rx)
if (rx)
val |= CONFIG0_FLOW_RX;
writel(val, port->gmac_base + GMAC_CONFIG0);
-
- spin_unlock_irqrestore(&port->config_lock, flags);
}
static void gmac_adjust_link(struct net_device *netdev)
@@ -782,7 +771,6 @@ static struct page *geth_freeq_claim(struct gemini_ethernet *geth,
unsigned int frag_len = 1 << geth->freeq_frag_order;
struct gmac_queue_page *gpage;
unsigned long index;
- unsigned long flags;
dma_addr_t page_mapping;
unsigned int slot;
struct page *page;
@@ -790,10 +778,11 @@ static struct page *geth_freeq_claim(struct gemini_ethernet *geth,
index = geth_freeq_mapping_index(geth, mapping);
- spin_lock_irqsave(&geth->freeq_lock, flags);
+ guard(spinlock_irqsave)(&geth->freeq_lock);
+
gpage = xa_load(&geth->freeq_mappings, index);
if (!gpage || !gpage->page || !gpage->fragments)
- goto err_unlock;
+ return NULL;
page = gpage->page;
page_mapping = gpage->mapping;
@@ -801,7 +790,7 @@ static struct page *geth_freeq_claim(struct gemini_ethernet *geth,
mapping - page_mapping <= PAGE_SIZE - frag_len &&
!((mapping - page_mapping) & (frag_len - 1));
if (!valid)
- goto err_unlock;
+ return NULL;
dma_sync_single_range_for_cpu(geth->dev, page_mapping,
mapping - page_mapping, frag_len,
@@ -819,12 +808,7 @@ static struct page *geth_freeq_claim(struct gemini_ethernet *geth,
}
*page_offs = mapping - page_mapping;
- spin_unlock_irqrestore(&geth->freeq_lock, flags);
return page;
-
-err_unlock:
- spin_unlock_irqrestore(&geth->freeq_lock, flags);
- return NULL;
}
static void gmac_cleanup_rxq(struct net_device *netdev)
@@ -990,7 +974,6 @@ static unsigned int geth_fill_freeq(struct gemini_ethernet *geth)
unsigned int fpp_order = PAGE_SHIFT - geth->freeq_frag_order;
unsigned int count = 0;
unsigned int pn, epn;
- unsigned long flags;
union dma_rwptr rw;
unsigned int m_pn;
@@ -1007,28 +990,26 @@ static unsigned int geth_fill_freeq(struct gemini_ethernet *geth)
if (ret)
break;
- spin_lock_irqsave(&geth->freeq_lock, flags);
-
- rw.bits32 = readl(geth->base + GLOBAL_SWFQ_RWPTR_REG);
- pn = rw.bits.wptr >> fpp_order;
- epn = (rw.bits.rptr >> fpp_order) - 1;
- epn &= m_pn;
- if (pn == epn) {
- ret = -ENOSPC;
- } else {
- ret = geth_freeq_add_page(geth, pn, page,
- page_mapping);
- if (!ret) {
- count += 1 << fpp_order;
- pn++;
- pn &= m_pn;
- writew(pn << fpp_order,
- geth->base + GLOBAL_SWFQ_RWPTR_REG + 2);
+ scoped_guard(spinlock_irqsave, &geth->freeq_lock) {
+ rw.bits32 = readl(geth->base + GLOBAL_SWFQ_RWPTR_REG);
+ pn = rw.bits.wptr >> fpp_order;
+ epn = (rw.bits.rptr >> fpp_order) - 1;
+ epn &= m_pn;
+ if (pn == epn) {
+ ret = -ENOSPC;
+ } else {
+ ret = geth_freeq_add_page(geth, pn, page,
+ page_mapping);
+ if (!ret) {
+ count += 1 << fpp_order;
+ pn++;
+ pn &= m_pn;
+ writew(pn << fpp_order,
+ geth->base + GLOBAL_SWFQ_RWPTR_REG + 2);
+ }
}
}
- spin_unlock_irqrestore(&geth->freeq_lock, flags);
-
if (ret) {
dma_unmap_single(geth->dev, page_mapping, PAGE_SIZE,
DMA_FROM_DEVICE);
@@ -1178,17 +1159,16 @@ static void geth_cleanup_freeq(struct gemini_ethernet *geth)
static void geth_set_freeq_irq(struct gemini_ethernet *geth, bool enable)
{
- unsigned long flags;
u32 val;
- spin_lock_irqsave(&geth->irq_lock, flags);
+ guard(spinlock_irqsave)(&geth->irq_lock);
+
val = readl(geth->base + GLOBAL_INTERRUPT_ENABLE_4_REG);
if (enable)
val |= SWFQ_EMPTY_INT_BIT;
else
val &= ~SWFQ_EMPTY_INT_BIT;
writel(val, geth->base + GLOBAL_INTERRUPT_ENABLE_4_REG);
- spin_unlock_irqrestore(&geth->irq_lock, flags);
}
/**
@@ -1267,12 +1247,11 @@ static void gmac_tx_irq_enable(struct net_device *netdev,
{
struct gemini_ethernet_port *port = netdev_priv(netdev);
struct gemini_ethernet *geth = port->geth;
- unsigned long flags;
u32 val, mask;
netdev_dbg(netdev, "%s device %d\n", __func__, netdev->dev_id);
- spin_lock_irqsave(&geth->irq_lock, flags);
+ guard(spinlock_irqsave)(&geth->irq_lock);
mask = GMAC0_IRQ0_TXQ0_INTS << (6 * netdev->dev_id + txq);
@@ -1282,8 +1261,6 @@ static void gmac_tx_irq_enable(struct net_device *netdev,
val = readl(geth->base + GLOBAL_INTERRUPT_ENABLE_0_REG);
val = en ? val | mask : val & ~mask;
writel(val, geth->base + GLOBAL_INTERRUPT_ENABLE_0_REG);
-
- spin_unlock_irqrestore(&geth->irq_lock, flags);
}
static void gmac_tx_irq(struct net_device *netdev, unsigned int txq_num)
@@ -1516,12 +1493,11 @@ static void gmac_enable_irq(struct net_device *netdev, int enable)
{
struct gemini_ethernet_port *port = netdev_priv(netdev);
struct gemini_ethernet *geth = port->geth;
- unsigned long flags;
u32 val, mask;
netdev_dbg(netdev, "%s device %d %s\n", __func__,
netdev->dev_id, enable ? "enable" : "disable");
- spin_lock_irqsave(&geth->irq_lock, flags);
+ guard(spinlock_irqsave)(&geth->irq_lock);
mask = GMAC0_IRQ0_2 << (netdev->dev_id * 2);
val = readl(geth->base + GLOBAL_INTERRUPT_ENABLE_0_REG);
@@ -1537,27 +1513,22 @@ static void gmac_enable_irq(struct net_device *netdev, int enable)
val = readl(geth->base + GLOBAL_INTERRUPT_ENABLE_4_REG);
val = enable ? (val | mask) : (val & ~mask);
writel(val, geth->base + GLOBAL_INTERRUPT_ENABLE_4_REG);
-
- spin_unlock_irqrestore(&geth->irq_lock, flags);
}
static void gmac_enable_rx_irq(struct net_device *netdev, int enable)
{
struct gemini_ethernet_port *port = netdev_priv(netdev);
struct gemini_ethernet *geth = port->geth;
- unsigned long flags;
u32 val, mask;
netdev_dbg(netdev, "%s device %d %s\n", __func__, netdev->dev_id,
enable ? "enable" : "disable");
- spin_lock_irqsave(&geth->irq_lock, flags);
+ guard(spinlock_irqsave)(&geth->irq_lock);
mask = DEFAULT_Q0_INT_BIT << netdev->dev_id;
val = readl(geth->base + GLOBAL_INTERRUPT_ENABLE_1_REG);
val = enable ? (val | mask) : (val & ~mask);
writel(val, geth->base + GLOBAL_INTERRUPT_ENABLE_1_REG);
-
- spin_unlock_irqrestore(&geth->irq_lock, flags);
}
static struct sk_buff *gmac_skb_if_good_frame(struct gemini_ethernet_port *port,
@@ -1622,17 +1593,16 @@ static unsigned int gmac_rx(struct net_device *netdev, unsigned int budget,
union gmac_rxdesc_3 word3;
struct page *page = NULL;
unsigned int page_offs;
- unsigned long flags;
unsigned short r, w;
union dma_rwptr rw;
dma_addr_t mapping;
- spin_lock_irqsave(&geth->irq_lock, flags);
- rw.bits32 = readl(ptr_reg);
- /* Reset interrupt as all packages until here are taken into account */
- writel(DEFAULT_Q0_INT_BIT << netdev->dev_id,
- geth->base + GLOBAL_INTERRUPT_STATUS_1_REG);
- spin_unlock_irqrestore(&geth->irq_lock, flags);
+ scoped_guard(spinlock_irqsave, &geth->irq_lock) {
+ rw.bits32 = readl(ptr_reg);
+ /* Reset interrupt as all packages until here are taken into account */
+ writel(DEFAULT_Q0_INT_BIT << netdev->dev_id,
+ geth->base + GLOBAL_INTERRUPT_STATUS_1_REG);
+ }
r = rw.bits.rptr;
w = rw.bits.wptr;
@@ -1871,9 +1841,8 @@ static void gmac_update_hw_stats(struct net_device *netdev)
struct gemini_ethernet_port *port = netdev_priv(netdev);
unsigned int rx_discards, rx_mcast, rx_bcast;
struct gemini_ethernet *geth = port->geth;
- unsigned long flags;
- spin_lock_irqsave(&geth->irq_lock, flags);
+ guard(spinlock_irqsave)(&geth->irq_lock);
u64_stats_update_begin(&port->ir_stats_syncp);
rx_discards = readl(port->gmac_base + GMAC_IN_DISCARDS);
@@ -1894,7 +1863,6 @@ static void gmac_update_hw_stats(struct net_device *netdev)
geth->base + GLOBAL_INTERRUPT_STATUS_4_REG);
u64_stats_update_end(&port->ir_stats_syncp);
- spin_unlock_irqrestore(&geth->irq_lock, flags);
}
/**
@@ -1980,13 +1948,14 @@ static irqreturn_t gmac_irq(int irq, void *data)
gmac_update_hw_stats(netdev);
if (val & (GMAC0_RX_OVERRUN_INT_BIT << (netdev->dev_id * 8))) {
- spin_lock(&geth->irq_lock);
- writel(GMAC0_RX_OVERRUN_INT_BIT << (netdev->dev_id * 8),
- geth->base + GLOBAL_INTERRUPT_STATUS_4_REG);
- u64_stats_update_begin(&port->ir_stats_syncp);
- ++port->stats.rx_fifo_errors;
- u64_stats_update_end(&port->ir_stats_syncp);
- spin_unlock(&geth->irq_lock);
+ scoped_guard(spinlock, &geth->irq_lock) {
+ writel(GMAC0_RX_OVERRUN_INT_BIT <<
+ (netdev->dev_id * 8),
+ geth->base + GLOBAL_INTERRUPT_STATUS_4_REG);
+ u64_stats_update_begin(&port->ir_stats_syncp);
+ ++port->stats.rx_fifo_errors;
+ u64_stats_update_end(&port->ir_stats_syncp);
+ }
}
return orr ? IRQ_HANDLED : IRQ_NONE;
@@ -2251,16 +2220,14 @@ static int gmac_set_features(struct net_device *netdev,
{
struct gemini_ethernet_port *port = netdev_priv(netdev);
int enable = features & NETIF_F_RXCSUM;
- unsigned long flags;
u32 reg;
- spin_lock_irqsave(&port->config_lock, flags);
+ guard(spinlock_irqsave)(&port->config_lock);
reg = readl(port->gmac_base + GMAC_CONFIG0);
reg = enable ? reg | CONFIG0_RX_CHKSUM : reg & ~CONFIG0_RX_CHKSUM;
writel(reg, port->gmac_base + GMAC_CONFIG0);
- spin_unlock_irqrestore(&port->config_lock, flags);
return 0;
}
@@ -2513,20 +2480,17 @@ static irqreturn_t gemini_port_irq_thread(int irq, void *data)
unsigned long irqmask = SWFQ_EMPTY_INT_BIT;
struct gemini_ethernet_port *port = data;
struct gemini_ethernet *geth;
- unsigned long flags;
geth = port->geth;
/* The queue is half empty so refill it */
geth_fill_freeq(geth);
- spin_lock_irqsave(&geth->irq_lock, flags);
+ guard(spinlock_irqsave)(&geth->irq_lock);
/* ACK queue interrupt */
writel(irqmask, geth->base + GLOBAL_INTERRUPT_STATUS_4_REG);
/* Enable queue interrupt again */
irqmask |= readl(geth->base + GLOBAL_INTERRUPT_ENABLE_4_REG);
writel(irqmask, geth->base + GLOBAL_INTERRUPT_ENABLE_4_REG);
- spin_unlock_irqrestore(&geth->irq_lock, flags);
-
return IRQ_HANDLED;
}
@@ -2538,7 +2502,7 @@ static irqreturn_t gemini_port_irq(int irq, void *data)
u32 val, en;
geth = port->geth;
- spin_lock(&geth->irq_lock);
+ guard(spinlock)(&geth->irq_lock);
val = readl(geth->base + GLOBAL_INTERRUPT_STATUS_4_REG);
en = readl(geth->base + GLOBAL_INTERRUPT_ENABLE_4_REG);
@@ -2554,8 +2518,6 @@ static irqreturn_t gemini_port_irq(int irq, void *data)
ret = IRQ_WAKE_THREAD;
}
- spin_unlock(&geth->irq_lock);
-
return ret;
}
--
2.55.0
next prev parent reply other threads:[~2026-09-28 8:51 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-28 8:50 [PATCH net-next v2 00/11] net: ethernet: cortina: Fix Gemini RX buffer management Linus Walleij
2026-09-28 8:50 ` [PATCH net-next v2 01/11] net: ethernet: cortina: Keep shared free queue parent-owned Linus Walleij
2026-09-30 2:50 ` netdev-bot+sashiko
2026-09-28 8:50 ` [PATCH net-next v2 02/11] net: ethernet: cortina: Drain free queue IRQ before resize Linus Walleij
2026-09-30 2:50 ` netdev-bot+sashiko
2026-09-28 8:50 ` [PATCH net-next v2 03/11] net: ethernet: cortina: Correct free queue DMA mappings Linus Walleij
2026-09-30 2:50 ` netdev-bot+sashiko
2026-09-28 8:50 ` [PATCH net-next v2 04/11] net: ethernet: cortina: Index free queue fragments with XArray Linus Walleij
2026-09-30 2:50 ` netdev-bot+sashiko
2026-09-28 8:50 ` [PATCH net-next v2 05/11] net: ethernet: cortina: Preserve in-flight free queue pages Linus Walleij
2026-09-30 2:50 ` netdev-bot+sashiko
2026-09-28 8:50 ` [PATCH net-next v2 06/11] net: ethernet: cortina: Rotate free queue page allocation Linus Walleij
2026-09-28 8:50 ` [PATCH net-next v2 07/11] net: ethernet: cortina: Synchronize RX fragments for the CPU Linus Walleij
2026-09-30 2:50 ` netdev-bot+sashiko
2026-09-28 8:50 ` [PATCH net-next v2 08/11] net: ethernet: cortina: Validate RX fragment lengths Linus Walleij
2026-09-30 2:50 ` netdev-bot+sashiko
2026-09-28 8:50 ` [PATCH net-next v2 09/11] net: ethernet: cortina: Release partial RX frames on stop Linus Walleij
2026-09-30 2:50 ` netdev-bot+sashiko
2026-09-28 8:50 ` [PATCH net-next v2 10/11] net: ethernet: cortina: Scale Gemini RX queues to system memory Linus Walleij
2026-09-28 8:50 ` Linus Walleij [this message]
2026-09-30 2:50 ` [PATCH net-next v2 11/11] net: ethernet: cortina: Use guard helpers for locking netdev-bot+sashiko
2026-10-01 9:51 ` [PATCH net-next v2 00/11] net: ethernet: cortina: Fix Gemini RX buffer management Paolo Abeni
2026-10-01 11:33 ` Linus Walleij
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260928-gemini-ethernet-fixes-3-v2-11-758a795d7a78@kernel.org \
--to=linusw@kernel.org \
--cc=andrew+netdev@lunn.ch \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=kuba@kernel.org \
--cc=mhun512@gmail.com \
--cc=mirq-linux@rere.qmqm.pl \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=ulli.kroll@googlemail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox