Netdev List
 help / color / mirror / Atom feed
* RE: [RFC Patch net-next v1 9/9] r8169: add support for ethtool
From: Javen @ 2026-04-22  7:47 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: hkallweit1@gmail.com, nic_swsd@realtek.com, andrew+netdev@lunn.ch,
	davem@davemloft.net, edumazet@google.com, kuba@kernel.org,
	pabeni@redhat.com, horms@kernel.org, netdev@vger.kernel.org,
	linux-kernel@vger.kernel.org
In-Reply-To: <c94f23f6-e353-4e88-af91-9e73d70d009d@lunn.ch>

>> +static int rtl8169_set_channels(struct net_device *dev,
>> +                             struct ethtool_channels *ch) {
>> +     struct rtl8169_private *tp = netdev_priv(dev);
>> +     bool if_running = netif_running(dev);
>> +     int i;
>> +
>> +     if (!tp->rss_support && (ch->rx_count > 1 || ch->tx_count > 1)) {
>> +             netdev_warn(dev, "This chip does not support multiple
>channels/RSS.\n");
>> +             return -EOPNOTSUPP;
>> +     }
>> +
>> +     if (ch->rx_count == 0 || ch->tx_count == 0)
>> +             return -EINVAL;
>> +     if (ch->rx_count > tp->HwSuppNumRxQueues ||
>> +         ch->tx_count > tp->HwSuppNumTxQueues)
>> +             return -EINVAL;
>> +     if (ch->other_count || ch->combined_count)
>> +             return -EINVAL;
>> +
>> +     if (ch->rx_count == tp->num_rx_rings &&
>> +         ch->tx_count == tp->num_tx_rings)
>> +             return 0;
>> +
>> +     if (if_running)
>> +             rtl8169_close(dev);
>
>I assume this releases all the memory from the rings?
>
>> +
>> +     tp->num_rx_rings = ch->rx_count;
>> +     tp->num_tx_rings = ch->tx_count;
>> +
>> +     tp->rss_enable = (tp->num_rx_rings > 1 && tp->rss_support);
>> +
>> +     for (i = 0; i < tp->HwSuppIndirTblEntries; i++) {
>> +             if (tp->rss_enable)
>> +                     tp->rss_indir_tbl[i] = ethtool_rxfh_indir_default(i, tp-
>>num_rx_rings);
>> +             else
>> +                     tp->rss_indir_tbl[i] = 0;
>> +     }
>> +
>> +     if (tp->rss_enable)
>> +             tp->InitRxDescType = RX_DESC_RING_TYPE_RSS;
>> +     else
>> +             tp->InitRxDescType = RX_DESC_RING_TYPE_DEAFULT;
>> +
>> +     if (if_running)
>> +             return rtl_open(dev);
>
>And this tries to allocate the memory needed for the rings? And if the system
>is under memory pressure, it fails and your network is dead?
>
>Please modify the code so that is first allocated the new rings and then frees
>the old rings, so you can fail gracefully.
>
>     Andrew

Thank you for your advice. I have updated the code accordingly. This patch is 
based on RFC Patch net-next 9/9.

This patch fixes issues when using ethtool -L to change the number of RX rings. 
Specifically, if allocating memory for the new RX rings fails, it now gracefully rolls 
back to the original state.
Additionally, it fixes a bug where ping or iperf would fail after manually setting 
8 RX rings (when the default suggested RSS queue number is only 1 or 2). This 
was caused by a missing call to rtl_set_irq_mask, which is now added.

---
 drivers/net/ethernet/realtek/r8169_main.c | 101 +++++++++++++++++++---
 1 file changed, 90 insertions(+), 11 deletions(-)

diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c
index 57087abe7d88..4b2abd3deee0 100644
--- a/drivers/net/ethernet/realtek/r8169_main.c
+++ b/drivers/net/ethernet/realtek/r8169_main.c
@@ -6116,6 +6116,8 @@ static void rtl8169_double_check_rss_support(struct rtl8169_private *tp)
 	if (tp->num_rx_rings >= 2) {
 		tp->rss_enable = 1;
 		tp->InitRxDescType = RX_DESC_RING_TYPE_RSS;
+	} else if (tp->num_rx_rings == 1 && tp->irq_nvecs > 1) {
+		tp->rss_enable = 0;
 	} else {
 		tp->rss_enable = 0;
 		if (tp->irq_nvecs > 1) {
@@ -6534,18 +6536,70 @@ static void rtl8169_get_channels(struct net_device *dev,
 	ch->combined_count = 0;
 }
 
+static int rtl8169_realloc_rx(struct rtl8169_private *tp,
+			      struct rtl8169_rx_ring *new_rx,
+			      int new_count)
+{
+	int i, ret;
+
+	new_rx[0].rdsar_reg = RxDescAddrLow;
+	for (i = 1; i < new_count; i++)
+		new_rx[i].rdsar_reg = (u16)(RDSAR_Q1_LOW + (i - 1) * 8);
+
+	for (i = 0; i < new_count; i++)
+		new_rx[i].num_rx_desc = NUM_RX_DESC;
+
+	for (i = 0; i < new_count; i++) {
+		struct rtl8169_rx_ring *ring = &new_rx[i];
+
+		ring->RxDescAllocSize = (NUM_RX_DESC + 1) * sizeof(struct RxDesc);
+		ring->RxDescArray = dma_alloc_coherent(&tp->pci_dev->dev,
+						       ring->RxDescAllocSize,
+						       &ring->RxPhyAddr,
+						       GFP_KERNEL);
+		if (!ring->RxDescArray) {
+			ret = -ENOMEM;
+			goto err_free;
+		}
+
+		memset(ring->Rx_databuff, 0, sizeof(ring->Rx_databuff));
+		ret = rtl8169_rx_fill(tp, ring);
+		if (ret) {
+			dma_free_coherent(&tp->pci_dev->dev, ring->RxDescAllocSize,
+					  ring->RxDescArray, ring->RxPhyAddr);
+			goto err_free;
+		}
+	}
+	return 0;
+
+err_free:
+	while (--i >= 0) {
+		rtl8169_rx_clear(tp, &new_rx[i]);
+		dma_free_coherent(&tp->pci_dev->dev, new_rx[i].RxDescAllocSize,
+				  new_rx[i].RxDescArray, new_rx[i].RxPhyAddr);
+	}
+	return ret;
+}
+
 static int rtl8169_set_channels(struct net_device *dev,
 				struct ethtool_channels *ch)
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
 	bool if_running = netif_running(dev);
-	int i;
+	struct rtl8169_rx_ring *new_rx;
+	u8 old_tx_desc_type = tp->InitRxDescType;
+	u8 new_desc_type;
+	bool new_rss_enable;
+	int i, ret;
 
 	if (!tp->rss_support && (ch->rx_count > 1 || ch->tx_count > 1)) {
 		netdev_warn(dev, "This chip does not support multiple channels/RSS.\n");
 		return -EOPNOTSUPP;
 	}
 
+	if (tp->features & RTL_FEATURE_MSI)
+		return -EINVAL;
+
 	if (ch->rx_count == 0 || ch->tx_count == 0)
 		return -EINVAL;
 	if (ch->rx_count > tp->HwSuppNumRxQueues ||
@@ -6558,13 +6612,39 @@ static int rtl8169_set_channels(struct net_device *dev,
 	    ch->tx_count == tp->num_tx_rings)
 		return 0;
 
-	if (if_running)
-		rtl8169_close(dev);
+	new_rss_enable = (ch->rx_count > 1 && tp->rss_support);
+	new_desc_type = new_rss_enable ? RX_DESC_RING_TYPE_RSS : RX_DESC_RING_TYPE_DEAFULT;
+	tp->InitRxDescType = new_desc_type;
+
+	if (!if_running) {
+		tp->num_rx_rings = ch->rx_count;
+		tp->rss_enable = new_rss_enable;
+		return 0;
+	}
+
+	new_rx = kcalloc(R8169_MAX_RX_QUEUES, sizeof(*new_rx), GFP_KERNEL);
+	if (!new_rx)
+		return -ENOMEM;
+
+	ret = rtl8169_realloc_rx(tp, new_rx, ch->rx_count);
+	if (ret) {
+		kfree(new_rx);
+		tp->InitRxDescType = old_tx_desc_type;
+		return ret;
+	}
+
+	netif_stop_queue(dev);
+	rtl8169_down(tp);
+
+	for (i = 0; i < tp->num_rx_rings; i++)
+		rtl8169_rx_clear(tp, &tp->rx_ring[i]);
+	rtl8169_free_rx_desc(tp);
 
 	tp->num_rx_rings = ch->rx_count;
-	tp->num_tx_rings = ch->tx_count;
+	tp->rss_enable = new_rss_enable;
 
-	tp->rss_enable = (tp->num_rx_rings > 1 && tp->rss_support);
+	memset(tp->rx_ring, 0, sizeof(tp->rx_ring));
+	memcpy(tp->rx_ring, new_rx, sizeof(*new_rx) * ch->rx_count);
 
 	for (i = 0; i < tp->HwSuppIndirTblEntries; i++) {
 		if (tp->rss_enable)
@@ -6573,13 +6653,12 @@ static int rtl8169_set_channels(struct net_device *dev,
 			tp->rss_indir_tbl[i] = 0;
 	}
 
-	if (tp->rss_enable)
-		tp->InitRxDescType = RX_DESC_RING_TYPE_RSS;
-	else
-		tp->InitRxDescType = RX_DESC_RING_TYPE_DEAFULT;
+	rtl_set_irq_mask(tp);
+
+	rtl8169_up(tp);
+	netif_start_queue(dev);
 
-	if (if_running)
-		return rtl_open(dev);
+	kfree(new_rx);
 
 	return 0;
 }
-- 
2.43.0


^ permalink raw reply related

* Re: [PATCH net 00/18] Remove a number of ISA and PCMCIA Ethernet drivers
From: Geert Uytterhoeven @ 2026-04-22  7:42 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Simon Horman, Jonathan Corbet, Shuah Khan,
	linux-kernel, netdev, linux-doc
In-Reply-To: <20260421-v7-0-0-net-next-driver-removal-v1-v1-0-69517c689d1f@lunn.ch>

Hi Andrew,

On Tue, 21 Apr 2026 at 21:31, Andrew Lunn <andrew@lunn.ch> wrote:
> These old drivers have not been much of a Maintenance burden until
> recently. Now there are more newbies using AI and fuzzers finding
> issues, resulting in more work for Maintainers. Fixing these old
> drivers make little sense, if it is not clear they have users.

Thanks for your series!

> These are all ISA and PCMCIA Ethernet devices, mostly from the last

Only the drivers that depend solely on ISA or PCMCIA are drivers
for ISA and PCMCIA devices.

These are not:

-       depends on (PCI || EISA) && HAS_IOPORT_MAP
-       depends on DIO
-       depends on MVME147
-       depends on ARM || (COMPILE_TEST && !PPC)
-       depends on MAC

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply

* Re: [PATCH net] tcp: make probe0 timer handle expired user timeout
From: Eric Dumazet @ 2026-04-22  7:39 UTC (permalink / raw)
  To: Altan Hacigumus
  Cc: Neal Cardwell, Kuniyuki Iwashima, David S . Miller, David Ahern,
	Jakub Kicinski, Paolo Abeni, Simon Horman, netdev, linux-kernel,
	Enke Chen
In-Reply-To: <CALjTKDkJ9L-88hdODbt-8D=eEDe6r5egtTfk_RnwgVq_NF+q+g@mail.gmail.com>

On Tue, Apr 21, 2026 at 8:31 PM Altan Hacigumus <ahacigu.linux@gmail.com> wrote:
>
> On Mon, Apr 20, 2026 at 9:58 PM Eric Dumazet <edumazet@google.com> wrote:
> >
> > On Mon, Apr 13, 2026 at 6:36 PM Altan Hacigumus <ahacigu.linux@gmail.com> wrote:
> > >
> > > tcp_clamp_probe0_to_user_timeout() computes remaining time in jiffies
> > > using subtraction with an unsigned lvalue.  If elapsed probing time
> > > already exceeds the configured TCP_USER_TIMEOUT, the subtraction
> > > underflows and yields a large value.
> > >
> > > Handle this expiration case similarly to tcp_clamp_rto_to_user_timeout().
> > >
> > > Fixes: 344db93ae3ee ("tcp: make TCP_USER_TIMEOUT accurate for zero window probes")
> > > Signed-off-by: Altan Hacigumus <ahacigu.linux@gmail.com>
> > > ---
> > >  net/ipv4/tcp_timer.c | 5 ++++-
> > >  1 file changed, 4 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c
> > > index 5a14a53a3c9e..4a43356a4e06 100644
> > > --- a/net/ipv4/tcp_timer.c
> > > +++ b/net/ipv4/tcp_timer.c
> > > @@ -50,7 +50,8 @@ static u32 tcp_clamp_rto_to_user_timeout(const struct sock *sk)
> > >  u32 tcp_clamp_probe0_to_user_timeout(const struct sock *sk, u32 when)
> > >  {
> > >         const struct inet_connection_sock *icsk = inet_csk(sk);
> > > -       u32 remaining, user_timeout;
> > > +       u32 user_timeout;
> > > +       s32 remaining;
> > >         s32 elapsed;
> > >
> > >         user_timeout = READ_ONCE(icsk->icsk_user_timeout);
> > > @@ -61,6 +62,8 @@ u32 tcp_clamp_probe0_to_user_timeout(const struct sock *sk, u32 when)
> > >         if (unlikely(elapsed < 0))
> > >                 elapsed = 0;
> > >         remaining = msecs_to_jiffies(user_timeout) - elapsed;
> > > +       if (remaining <= 0)
> > > +               return 1;
> >
> > I do not think this chunk is needed ?
> > If @remaining is signed, then perhaps change the following line to:
> >
> > remaining = max_t(int, remaining, TCP_TIMEOUT_MIN);
> >
>
> The if (remaining <= 0) return 1 handles the already-expired case and
> mirrors the logic in tcp_clamp_rto_to_user_timeout().

tcp_clamp_rto_to_user_timeout() has two conditionals.

if (remaining <= 0)
   return 1;
return min_t(u32, icsk->icsk_rto, msecs_to_jiffies(remaining));

First one was to avoid to call msecs_to_jiffies() with a negative number.

tcp_clamp_probe0_to_user_timeout() has 3 tests already, you want to
add a fourth one...
I would prefer something less obscure.
We do not care if we return 1 or 2 (TCP_TIMEOUT_MIN) jiffies

>
> max_t(s32, remaining, TCP_TIMEOUT_MIN) with remaining changed to s32
> also fixes the underflow; I used the explicit early return for symmetry
> with the RTO helper, but I can switch that in v2 if you prefer.
>
> > Also, it would be great to have a  new packetdrill test.
> >
>
> With packetdrill, AFAICS it would require a late ACK to be processed
> after TCP_USER_TIMEOUT has elapsed but before tcp_probe_timer() runs the
> abort check - i.e. a race between the RX softirq path and the timer.
> This is not purely an event/packet ordering problem, so it is not clear
> to me how a deterministic behavior can be simulated with packetdrill
> without tying it to exact probe timing.

I was trying to sense if the bug was serious or not, considering last
tcp_clamp_probe0_to_user_timeout()
statement is:

return min_t(u32, remaining, when);

Perhaps you should give more details in the changelog. What were the
symptoms of this bug, for TCP_USER_TIMEOUT users.

^ permalink raw reply

* [PATCH bpf v3] bpf: Fix NULL pointer dereference in bpf_sk_storage_clone and diag paths
From: Weiming Shi @ 2026-04-22  6:54 UTC (permalink / raw)
  To: David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni
  Cc: Simon Horman, Martin KaFai Lau, Alexei Starovoitov, Amery Hung,
	Leon Hwang, Kees Cook, Fushuai Wang, Menglong Dong, netdev, bpf,
	Xiang Mei, Weiming Shi

bpf_selem_unlink_nofail() sets SDATA(selem)->smap to NULL before
removing the selem from the storage hlist. A concurrent RCU reader in
bpf_sk_storage_clone() can observe the selem still on the list with
smap already NULL, causing a NULL pointer dereference.

 general protection fault, probably for non-canonical address 0xdffffc000000000a:
 KASAN: null-ptr-deref in range [0x0000000000000050-0x0000000000000057]
 RIP: 0010:bpf_sk_storage_clone+0x1cd/0xaa0 net/core/bpf_sk_storage.c:174
 Call Trace:
  <IRQ>
  sk_clone+0xfed/0x1980 net/core/sock.c:2591
  inet_csk_clone_lock+0x30/0x760 net/ipv4/inet_connection_sock.c:1222
  tcp_create_openreq_child+0x35/0x2680 net/ipv4/tcp_minisocks.c:571
  tcp_v4_syn_recv_sock+0x123/0xf90 net/ipv4/tcp_ipv4.c:1729
  tcp_check_req+0x8e1/0x2580 include/net/tcp.h:855
  tcp_v4_rcv+0x1845/0x3b80 net/ipv4/tcp_ipv4.c:2347

Add a NULL check for smap in bpf_sk_storage_clone().
bpf_sk_storage_diag_put_all() and bpf_sk_storage_diag_put() have the
same unprotected dereference pattern, add NULL checks there as well and
pass the validated smap to diag_get() so it no longer performs its own
rcu_dereference.

Fixes: 5d800f87d0a5 ("bpf: Support lockless unlink when freeing map or local storage")
Reported-by: Xiang Mei <xmei5@asu.edu>
Signed-off-by: Weiming Shi <bestswngs@gmail.com>
---
v3:
  pass smap to diag_get()
v2:
  drop the NULL check in diag_get(); The caller already checks smap for
NULL.

 net/core/bpf_sk_storage.c | 18 ++++++++++++------
 1 file changed, 12 insertions(+), 6 deletions(-)

diff --git a/net/core/bpf_sk_storage.c b/net/core/bpf_sk_storage.c
index f8338acebf077..1f9bd0005883b 100644
--- a/net/core/bpf_sk_storage.c
+++ b/net/core/bpf_sk_storage.c
@@ -172,7 +172,7 @@ int bpf_sk_storage_clone(const struct sock *sk, struct sock *newsk)
 		struct bpf_map *map;
 
 		smap = rcu_dereference(SDATA(selem)->smap);
-		if (!(smap->map.map_flags & BPF_F_CLONE))
+		if (!smap || !(smap->map.map_flags & BPF_F_CLONE))
 			continue;
 
 		/* Note that for lockless listeners adding new element
@@ -534,10 +534,10 @@ bpf_sk_storage_diag_alloc(const struct nlattr *nla_stgs)
 }
 EXPORT_SYMBOL_GPL(bpf_sk_storage_diag_alloc);
 
-static int diag_get(struct bpf_local_storage_data *sdata, struct sk_buff *skb)
+static int diag_get(struct bpf_local_storage_map *smap,
+		    struct bpf_local_storage_data *sdata, struct sk_buff *skb)
 {
 	struct nlattr *nla_stg, *nla_value;
-	struct bpf_local_storage_map *smap;
 
 	/* It cannot exceed max nlattr's payload */
 	BUILD_BUG_ON(U16_MAX - NLA_HDRLEN < BPF_LOCAL_STORAGE_MAX_VALUE_SIZE);
@@ -546,7 +546,6 @@ static int diag_get(struct bpf_local_storage_data *sdata, struct sk_buff *skb)
 	if (!nla_stg)
 		return -EMSGSIZE;
 
-	smap = rcu_dereference(sdata->smap);
 	if (nla_put_u32(skb, SK_DIAG_BPF_STORAGE_MAP_ID, smap->map.id))
 		goto errout;
 
@@ -599,9 +598,11 @@ static int bpf_sk_storage_diag_put_all(struct sock *sk, struct sk_buff *skb,
 	saved_len = skb->len;
 	hlist_for_each_entry_rcu(selem, &sk_storage->list, snode) {
 		smap = rcu_dereference(SDATA(selem)->smap);
+		if (!smap)
+			continue;
 		diag_size += nla_value_size(smap->map.value_size);
 
-		if (nla_stgs && diag_get(SDATA(selem), skb))
+		if (nla_stgs && diag_get(smap, SDATA(selem), skb))
 			/* Continue to learn diag_size */
 			err = -EMSGSIZE;
 	}
@@ -633,6 +634,7 @@ int bpf_sk_storage_diag_put(struct bpf_sk_storage_diag *diag,
 	unsigned int diag_size = nla_total_size(0);
 	struct bpf_local_storage *sk_storage;
 	struct bpf_local_storage_data *sdata;
+	struct bpf_local_storage_map *smap;
 	struct nlattr *nla_stgs;
 	unsigned int saved_len;
 	int err = 0;
@@ -668,7 +670,11 @@ int bpf_sk_storage_diag_put(struct bpf_sk_storage_diag *diag,
 
 		diag_size += nla_value_size(diag->maps[i]->value_size);
 
-		if (nla_stgs && diag_get(sdata, skb))
+		smap = rcu_dereference(sdata->smap);
+		if (!smap)
+			continue;
+
+		if (nla_stgs && diag_get(smap, sdata, skb))
 			/* Continue to learn diag_size */
 			err = -EMSGSIZE;
 	}
-- 
2.43.0


^ permalink raw reply related

* Re: [PATCH net 06/18] drivers: net: amd: Remove hplance and mvme147
From: Geert Uytterhoeven @ 2026-04-22  7:37 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Simon Horman, Jonathan Corbet, Shuah Khan,
	linux-kernel, netdev, linux-doc, linux-m68k
In-Reply-To: <20260421-v7-0-0-net-next-driver-removal-v1-v1-6-69517c689d1f@lunn.ch>

CC linux-m68k

On Tue, 21 Apr 2026 at 21:33, Andrew Lunn <andrew@lunn.ch> wrote:
> These drivers use the 7990 core with wrappers for the HP300 and
> Motorola MVME147 SBC circa 1998. It is unlikely they are used with a
> modern kernel.
>
> Signed-off-by: Andrew Lunn <andrew@lunn.ch>
> ---
>  drivers/net/ethernet/amd/7990.c    | 671 -------------------------------------
>  drivers/net/ethernet/amd/7990.h    | 251 --------------
>  drivers/net/ethernet/amd/Kconfig   |  18 -
>  drivers/net/ethernet/amd/Makefile  |   2 -
>  drivers/net/ethernet/amd/hplance.c | 238 -------------
>  drivers/net/ethernet/amd/hplance.h |  27 --
>  drivers/net/ethernet/amd/mvme147.c | 198 -----------
>  7 files changed, 1405 deletions(-)
>
> diff --git a/drivers/net/ethernet/amd/7990.c b/drivers/net/ethernet/amd/7990.c
> deleted file mode 100644
> index 27792a52b6cf..000000000000
> --- a/drivers/net/ethernet/amd/7990.c
> +++ /dev/null
> @@ -1,671 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0-only
> -/*
> - * 7990.c -- LANCE ethernet IC generic routines.
> - * This is an attempt to separate out the bits of various ethernet
> - * drivers that are common because they all use the AMD 7990 LANCE
> - * (Local Area Network Controller for Ethernet) chip.
> - *
> - * Copyright (C) 05/1998 Peter Maydell <pmaydell@chiark.greenend.org.uk>
> - *
> - * Most of this stuff was obtained by looking at other LANCE drivers,
> - * in particular a2065.[ch]. The AMD C-LANCE datasheet was also helpful.
> - * NB: this was made easy by the fact that Jes Sorensen had cleaned up
> - * most of a2025 and sunlance with the aim of merging them, so the
> - * common code was pretty obvious.
> - */
> -#include <linux/crc32.h>
> -#include <linux/delay.h>
> -#include <linux/errno.h>
> -#include <linux/netdevice.h>
> -#include <linux/etherdevice.h>
> -#include <linux/module.h>
> -#include <linux/kernel.h>
> -#include <linux/types.h>
> -#include <linux/fcntl.h>
> -#include <linux/interrupt.h>
> -#include <linux/ioport.h>
> -#include <linux/in.h>
> -#include <linux/route.h>
> -#include <linux/string.h>
> -#include <linux/skbuff.h>
> -#include <linux/pgtable.h>
> -#include <asm/irq.h>
> -/* Used for the temporal inet entries and routing */
> -#include <linux/socket.h>
> -#include <linux/bitops.h>
> -
> -#include <asm/io.h>
> -#include <asm/dma.h>
> -#ifdef CONFIG_HP300
> -#include <asm/blinken.h>
> -#endif
> -
> -#include "7990.h"
> -
> -#define WRITERAP(lp, x)        out_be16(lp->base + LANCE_RAP, (x))
> -#define WRITERDP(lp, x)        out_be16(lp->base + LANCE_RDP, (x))
> -#define READRDP(lp)    in_be16(lp->base + LANCE_RDP)
> -
> -#if IS_ENABLED(CONFIG_HPLANCE)
> -#include "hplance.h"
> -
> -#undef WRITERAP
> -#undef WRITERDP
> -#undef READRDP
> -
> -#if IS_ENABLED(CONFIG_MVME147_NET)
> -
> -/* Lossage Factor Nine, Mr Sulu. */
> -#define WRITERAP(lp, x)        (lp->writerap(lp, x))
> -#define WRITERDP(lp, x)        (lp->writerdp(lp, x))
> -#define READRDP(lp)    (lp->readrdp(lp))
> -
> -#else
> -
> -/* These inlines can be used if only CONFIG_HPLANCE is defined */
> -static inline void WRITERAP(struct lance_private *lp, __u16 value)
> -{
> -       do {
> -               out_be16(lp->base + HPLANCE_REGOFF + LANCE_RAP, value);
> -       } while ((in_8(lp->base + HPLANCE_STATUS) & LE_ACK) == 0);
> -}
> -
> -static inline void WRITERDP(struct lance_private *lp, __u16 value)
> -{
> -       do {
> -               out_be16(lp->base + HPLANCE_REGOFF + LANCE_RDP, value);
> -       } while ((in_8(lp->base + HPLANCE_STATUS) & LE_ACK) == 0);
> -}
> -
> -static inline __u16 READRDP(struct lance_private *lp)
> -{
> -       __u16 value;
> -       do {
> -               value = in_be16(lp->base + HPLANCE_REGOFF + LANCE_RDP);
> -       } while ((in_8(lp->base + HPLANCE_STATUS) & LE_ACK) == 0);
> -       return value;
> -}
> -
> -#endif
> -#endif /* IS_ENABLED(CONFIG_HPLANCE) */
> -
> -/* debugging output macros, various flavours */
> -/* #define TEST_HITS */
> -#ifdef UNDEF
> -#define PRINT_RINGS() \
> -do { \
> -       int t; \
> -       for (t = 0; t < RX_RING_SIZE; t++) { \
> -               printk("R%d: @(%02X %04X) len %04X, mblen %04X, bits %02X\n", \
> -                      t, ib->brx_ring[t].rmd1_hadr, ib->brx_ring[t].rmd0, \
> -                      ib->brx_ring[t].length, \
> -                      ib->brx_ring[t].mblength, ib->brx_ring[t].rmd1_bits); \
> -       } \
> -       for (t = 0; t < TX_RING_SIZE; t++) { \
> -               printk("T%d: @(%02X %04X) len %04X, misc %04X, bits %02X\n", \
> -                      t, ib->btx_ring[t].tmd1_hadr, ib->btx_ring[t].tmd0, \
> -                      ib->btx_ring[t].length, \
> -                      ib->btx_ring[t].misc, ib->btx_ring[t].tmd1_bits); \
> -       } \
> -} while (0)
> -#else
> -#define PRINT_RINGS()
> -#endif
> -
> -/* Load the CSR registers. The LANCE has to be STOPped when we do this! */
> -static void load_csrs(struct lance_private *lp)
> -{
> -       volatile struct lance_init_block *aib = lp->lance_init_block;
> -       int leptr;
> -
> -       leptr = LANCE_ADDR(aib);
> -
> -       WRITERAP(lp, LE_CSR1);                    /* load address of init block */
> -       WRITERDP(lp, leptr & 0xFFFF);
> -       WRITERAP(lp, LE_CSR2);
> -       WRITERDP(lp, leptr >> 16);
> -       WRITERAP(lp, LE_CSR3);
> -       WRITERDP(lp, lp->busmaster_regval);       /* set byteswap/ALEctrl/byte ctrl */
> -
> -       /* Point back to csr0 */
> -       WRITERAP(lp, LE_CSR0);
> -}
> -
> -/* #define to 0 or 1 appropriately */
> -#define DEBUG_IRING 0
> -/* Set up the Lance Rx and Tx rings and the init block */
> -static void lance_init_ring(struct net_device *dev)
> -{
> -       struct lance_private *lp = netdev_priv(dev);
> -       volatile struct lance_init_block *ib = lp->init_block;
> -       volatile struct lance_init_block *aib; /* for LANCE_ADDR computations */
> -       int leptr;
> -       int i;
> -
> -       aib = lp->lance_init_block;
> -
> -       lp->rx_new = lp->tx_new = 0;
> -       lp->rx_old = lp->tx_old = 0;
> -
> -       ib->mode = LE_MO_PROM;                             /* normal, enable Tx & Rx */
> -
> -       /* Copy the ethernet address to the lance init block
> -        * Notice that we do a byteswap if we're big endian.
> -        * [I think this is the right criterion; at least, sunlance,
> -        * a2065 and atarilance do the byteswap and lance.c (PC) doesn't.
> -        * However, the datasheet says that the BSWAP bit doesn't affect
> -        * the init block, so surely it should be low byte first for
> -        * everybody? Um.]
> -        * We could define the ib->physaddr as three 16bit values and
> -        * use (addr[1] << 8) | addr[0] & co, but this is more efficient.
> -        */
> -#ifdef __BIG_ENDIAN
> -       ib->phys_addr[0] = dev->dev_addr[1];
> -       ib->phys_addr[1] = dev->dev_addr[0];
> -       ib->phys_addr[2] = dev->dev_addr[3];
> -       ib->phys_addr[3] = dev->dev_addr[2];
> -       ib->phys_addr[4] = dev->dev_addr[5];
> -       ib->phys_addr[5] = dev->dev_addr[4];
> -#else
> -       for (i = 0; i < 6; i++)
> -              ib->phys_addr[i] = dev->dev_addr[i];
> -#endif
> -
> -       if (DEBUG_IRING)
> -               printk("TX rings:\n");
> -
> -       lp->tx_full = 0;
> -       /* Setup the Tx ring entries */
> -       for (i = 0; i < (1 << lp->lance_log_tx_bufs); i++) {
> -               leptr = LANCE_ADDR(&aib->tx_buf[i][0]);
> -               ib->btx_ring[i].tmd0      = leptr;
> -               ib->btx_ring[i].tmd1_hadr = leptr >> 16;
> -               ib->btx_ring[i].tmd1_bits = 0;
> -               ib->btx_ring[i].length    = 0xf000; /* The ones required by tmd2 */
> -               ib->btx_ring[i].misc      = 0;
> -               if (DEBUG_IRING)
> -                       printk("%d: 0x%8.8x\n", i, leptr);
> -       }
> -
> -       /* Setup the Rx ring entries */
> -       if (DEBUG_IRING)
> -               printk("RX rings:\n");
> -       for (i = 0; i < (1 << lp->lance_log_rx_bufs); i++) {
> -               leptr = LANCE_ADDR(&aib->rx_buf[i][0]);
> -
> -               ib->brx_ring[i].rmd0      = leptr;
> -               ib->brx_ring[i].rmd1_hadr = leptr >> 16;
> -               ib->brx_ring[i].rmd1_bits = LE_R1_OWN;
> -               /* 0xf000 == bits that must be one (reserved, presumably) */
> -               ib->brx_ring[i].length    = -RX_BUFF_SIZE | 0xf000;
> -               ib->brx_ring[i].mblength  = 0;
> -               if (DEBUG_IRING)
> -                       printk("%d: 0x%8.8x\n", i, leptr);
> -       }
> -
> -       /* Setup the initialization block */
> -
> -       /* Setup rx descriptor pointer */
> -       leptr = LANCE_ADDR(&aib->brx_ring);
> -       ib->rx_len = (lp->lance_log_rx_bufs << 13) | (leptr >> 16);
> -       ib->rx_ptr = leptr;
> -       if (DEBUG_IRING)
> -               printk("RX ptr: %8.8x\n", leptr);
> -
> -       /* Setup tx descriptor pointer */
> -       leptr = LANCE_ADDR(&aib->btx_ring);
> -       ib->tx_len = (lp->lance_log_tx_bufs << 13) | (leptr >> 16);
> -       ib->tx_ptr = leptr;
> -       if (DEBUG_IRING)
> -               printk("TX ptr: %8.8x\n", leptr);
> -
> -       /* Clear the multicast filter */
> -       ib->filter[0] = 0;
> -       ib->filter[1] = 0;
> -       PRINT_RINGS();
> -}
> -
> -/* LANCE must be STOPped before we do this, too... */
> -static int init_restart_lance(struct lance_private *lp)
> -{
> -       int i;
> -
> -       WRITERAP(lp, LE_CSR0);
> -       WRITERDP(lp, LE_C0_INIT);
> -
> -       /* Need a hook here for sunlance ledma stuff */
> -
> -       /* Wait for the lance to complete initialization */
> -       for (i = 0; (i < 100) && !(READRDP(lp) & (LE_C0_ERR | LE_C0_IDON)); i++)
> -               barrier();
> -       if ((i == 100) || (READRDP(lp) & LE_C0_ERR)) {
> -               printk("LANCE unopened after %d ticks, csr0=%4.4x.\n", i, READRDP(lp));
> -               return -1;
> -       }
> -
> -       /* Clear IDON by writing a "1", enable interrupts and start lance */
> -       WRITERDP(lp, LE_C0_IDON);
> -       WRITERDP(lp, LE_C0_INEA | LE_C0_STRT);
> -
> -       return 0;
> -}
> -
> -static int lance_reset(struct net_device *dev)
> -{
> -       struct lance_private *lp = netdev_priv(dev);
> -       int status;
> -
> -       /* Stop the lance */
> -       WRITERAP(lp, LE_CSR0);
> -       WRITERDP(lp, LE_C0_STOP);
> -
> -       load_csrs(lp);
> -       lance_init_ring(dev);
> -       netif_trans_update(dev); /* prevent tx timeout */
> -       status = init_restart_lance(lp);
> -#ifdef DEBUG_DRIVER
> -       printk("Lance restart=%d\n", status);
> -#endif
> -       return status;
> -}
> -
> -static int lance_rx(struct net_device *dev)
> -{
> -       struct lance_private *lp = netdev_priv(dev);
> -       volatile struct lance_init_block *ib = lp->init_block;
> -       volatile struct lance_rx_desc *rd;
> -       unsigned char bits;
> -#ifdef TEST_HITS
> -       int i;
> -#endif
> -
> -#ifdef TEST_HITS
> -       printk("[");
> -       for (i = 0; i < RX_RING_SIZE; i++) {
> -               if (i == lp->rx_new)
> -                       printk("%s",
> -                              ib->brx_ring[i].rmd1_bits & LE_R1_OWN ? "_" : "X");
> -               else
> -                       printk("%s",
> -                             ib->brx_ring[i].rmd1_bits & LE_R1_OWN ? "." : "1");
> -       }
> -       printk("]");
> -#endif
> -#ifdef CONFIG_HP300
> -       blinken_leds(0x40, 0);
> -#endif
> -       WRITERDP(lp, LE_C0_RINT | LE_C0_INEA);     /* ack Rx int, reenable ints */
> -       for (rd = &ib->brx_ring[lp->rx_new];     /* For each Rx ring we own... */
> -            !((bits = rd->rmd1_bits) & LE_R1_OWN);
> -            rd = &ib->brx_ring[lp->rx_new]) {
> -
> -               /* We got an incomplete frame? */
> -               if ((bits & LE_R1_POK) != LE_R1_POK) {
> -                       dev->stats.rx_over_errors++;
> -                       dev->stats.rx_errors++;
> -                       continue;
> -               } else if (bits & LE_R1_ERR) {
> -                       /* Count only the end frame as a rx error,
> -                        * not the beginning
> -                        */
> -                       if (bits & LE_R1_BUF)
> -                               dev->stats.rx_fifo_errors++;
> -                       if (bits & LE_R1_CRC)
> -                               dev->stats.rx_crc_errors++;
> -                       if (bits & LE_R1_OFL)
> -                               dev->stats.rx_over_errors++;
> -                       if (bits & LE_R1_FRA)
> -                               dev->stats.rx_frame_errors++;
> -                       if (bits & LE_R1_EOP)
> -                               dev->stats.rx_errors++;
> -               } else {
> -                       int len = (rd->mblength & 0xfff) - 4;
> -                       struct sk_buff *skb = netdev_alloc_skb(dev, len + 2);
> -
> -                       if (!skb) {
> -                               dev->stats.rx_dropped++;
> -                               rd->mblength = 0;
> -                               rd->rmd1_bits = LE_R1_OWN;
> -                               lp->rx_new = (lp->rx_new + 1) & lp->rx_ring_mod_mask;
> -                               return 0;
> -                       }
> -
> -                       skb_reserve(skb, 2);           /* 16 byte align */
> -                       skb_put(skb, len);             /* make room */
> -                       skb_copy_to_linear_data(skb,
> -                                        (unsigned char *)&(ib->rx_buf[lp->rx_new][0]),
> -                                        len);
> -                       skb->protocol = eth_type_trans(skb, dev);
> -                       netif_rx(skb);
> -                       dev->stats.rx_packets++;
> -                       dev->stats.rx_bytes += len;
> -               }
> -
> -               /* Return the packet to the pool */
> -               rd->mblength = 0;
> -               rd->rmd1_bits = LE_R1_OWN;
> -               lp->rx_new = (lp->rx_new + 1) & lp->rx_ring_mod_mask;
> -       }
> -       return 0;
> -}
> -
> -static int lance_tx(struct net_device *dev)
> -{
> -       struct lance_private *lp = netdev_priv(dev);
> -       volatile struct lance_init_block *ib = lp->init_block;
> -       volatile struct lance_tx_desc *td;
> -       int i, j;
> -       int status;
> -
> -#ifdef CONFIG_HP300
> -       blinken_leds(0x80, 0);
> -#endif
> -       /* csr0 is 2f3 */
> -       WRITERDP(lp, LE_C0_TINT | LE_C0_INEA);
> -       /* csr0 is 73 */
> -
> -       j = lp->tx_old;
> -       for (i = j; i != lp->tx_new; i = j) {
> -               td = &ib->btx_ring[i];
> -
> -               /* If we hit a packet not owned by us, stop */
> -               if (td->tmd1_bits & LE_T1_OWN)
> -                       break;
> -
> -               if (td->tmd1_bits & LE_T1_ERR) {
> -                       status = td->misc;
> -
> -                       dev->stats.tx_errors++;
> -                       if (status & LE_T3_RTY)
> -                               dev->stats.tx_aborted_errors++;
> -                       if (status & LE_T3_LCOL)
> -                               dev->stats.tx_window_errors++;
> -
> -                       if (status & LE_T3_CLOS) {
> -                               dev->stats.tx_carrier_errors++;
> -                               if (lp->auto_select) {
> -                                       lp->tpe = 1 - lp->tpe;
> -                                       printk("%s: Carrier Lost, trying %s\n",
> -                                              dev->name,
> -                                              lp->tpe ? "TPE" : "AUI");
> -                                       /* Stop the lance */
> -                                       WRITERAP(lp, LE_CSR0);
> -                                       WRITERDP(lp, LE_C0_STOP);
> -                                       lance_init_ring(dev);
> -                                       load_csrs(lp);
> -                                       init_restart_lance(lp);
> -                                       return 0;
> -                               }
> -                       }
> -
> -                       /* buffer errors and underflows turn off the transmitter */
> -                       /* Restart the adapter */
> -                       if (status & (LE_T3_BUF|LE_T3_UFL)) {
> -                               dev->stats.tx_fifo_errors++;
> -
> -                               printk("%s: Tx: ERR_BUF|ERR_UFL, restarting\n",
> -                                      dev->name);
> -                               /* Stop the lance */
> -                               WRITERAP(lp, LE_CSR0);
> -                               WRITERDP(lp, LE_C0_STOP);
> -                               lance_init_ring(dev);
> -                               load_csrs(lp);
> -                               init_restart_lance(lp);
> -                               return 0;
> -                       }
> -               } else if ((td->tmd1_bits & LE_T1_POK) == LE_T1_POK) {
> -                       /*
> -                        * So we don't count the packet more than once.
> -                        */
> -                       td->tmd1_bits &= ~(LE_T1_POK);
> -
> -                       /* One collision before packet was sent. */
> -                       if (td->tmd1_bits & LE_T1_EONE)
> -                               dev->stats.collisions++;
> -
> -                       /* More than one collision, be optimistic. */
> -                       if (td->tmd1_bits & LE_T1_EMORE)
> -                               dev->stats.collisions += 2;
> -
> -                       dev->stats.tx_packets++;
> -               }
> -
> -               j = (j + 1) & lp->tx_ring_mod_mask;
> -       }
> -       lp->tx_old = j;
> -       WRITERDP(lp, LE_C0_TINT | LE_C0_INEA);
> -       return 0;
> -}
> -
> -static irqreturn_t
> -lance_interrupt(int irq, void *dev_id)
> -{
> -       struct net_device *dev = (struct net_device *)dev_id;
> -       struct lance_private *lp = netdev_priv(dev);
> -       int csr0;
> -
> -       spin_lock(&lp->devlock);
> -
> -       WRITERAP(lp, LE_CSR0);              /* LANCE Controller Status */
> -       csr0 = READRDP(lp);
> -
> -       PRINT_RINGS();
> -
> -       if (!(csr0 & LE_C0_INTR)) {     /* Check if any interrupt has */
> -               spin_unlock(&lp->devlock);
> -               return IRQ_NONE;        /* been generated by the Lance. */
> -       }
> -
> -       /* Acknowledge all the interrupt sources ASAP */
> -       WRITERDP(lp, csr0 & ~(LE_C0_INEA|LE_C0_TDMD|LE_C0_STOP|LE_C0_STRT|LE_C0_INIT));
> -
> -       if ((csr0 & LE_C0_ERR)) {
> -               /* Clear the error condition */
> -               WRITERDP(lp, LE_C0_BABL|LE_C0_ERR|LE_C0_MISS|LE_C0_INEA);
> -       }
> -
> -       if (csr0 & LE_C0_RINT)
> -               lance_rx(dev);
> -
> -       if (csr0 & LE_C0_TINT)
> -               lance_tx(dev);
> -
> -       /* Log misc errors. */
> -       if (csr0 & LE_C0_BABL)
> -               dev->stats.tx_errors++;       /* Tx babble. */
> -       if (csr0 & LE_C0_MISS)
> -               dev->stats.rx_errors++;       /* Missed a Rx frame. */
> -       if (csr0 & LE_C0_MERR) {
> -               printk("%s: Bus master arbitration failure, status %4.4x.\n",
> -                      dev->name, csr0);
> -               /* Restart the chip. */
> -               WRITERDP(lp, LE_C0_STRT);
> -       }
> -
> -       if (lp->tx_full && netif_queue_stopped(dev) && (TX_BUFFS_AVAIL >= 0)) {
> -               lp->tx_full = 0;
> -               netif_wake_queue(dev);
> -       }
> -
> -       WRITERAP(lp, LE_CSR0);
> -       WRITERDP(lp, LE_C0_BABL|LE_C0_CERR|LE_C0_MISS|LE_C0_MERR|LE_C0_IDON|LE_C0_INEA);
> -
> -       spin_unlock(&lp->devlock);
> -       return IRQ_HANDLED;
> -}
> -
> -int lance_open(struct net_device *dev)
> -{
> -       struct lance_private *lp = netdev_priv(dev);
> -       int res;
> -
> -       /* Install the Interrupt handler. Or we could shunt this out to specific drivers? */
> -       if (request_irq(lp->irq, lance_interrupt, IRQF_SHARED, lp->name, dev))
> -               return -EAGAIN;
> -
> -       res = lance_reset(dev);
> -       spin_lock_init(&lp->devlock);
> -       netif_start_queue(dev);
> -
> -       return res;
> -}
> -EXPORT_SYMBOL_GPL(lance_open);
> -
> -int lance_close(struct net_device *dev)
> -{
> -       struct lance_private *lp = netdev_priv(dev);
> -
> -       netif_stop_queue(dev);
> -
> -       /* Stop the LANCE */
> -       WRITERAP(lp, LE_CSR0);
> -       WRITERDP(lp, LE_C0_STOP);
> -
> -       free_irq(lp->irq, dev);
> -
> -       return 0;
> -}
> -EXPORT_SYMBOL_GPL(lance_close);
> -
> -void lance_tx_timeout(struct net_device *dev, unsigned int txqueue)
> -{
> -       printk("lance_tx_timeout\n");
> -       lance_reset(dev);
> -       netif_trans_update(dev); /* prevent tx timeout */
> -       netif_wake_queue(dev);
> -}
> -EXPORT_SYMBOL_GPL(lance_tx_timeout);
> -
> -netdev_tx_t lance_start_xmit(struct sk_buff *skb, struct net_device *dev)
> -{
> -       struct lance_private *lp = netdev_priv(dev);
> -       volatile struct lance_init_block *ib = lp->init_block;
> -       int entry, skblen, len;
> -       static int outs;
> -       unsigned long flags;
> -
> -       netif_stop_queue(dev);
> -
> -       if (!TX_BUFFS_AVAIL) {
> -               dev_consume_skb_any(skb);
> -               return NETDEV_TX_OK;
> -       }
> -
> -       skblen = skb->len;
> -
> -#ifdef DEBUG_DRIVER
> -       /* dump the packet */
> -       {
> -               int i;
> -
> -               for (i = 0; i < 64; i++) {
> -                       if ((i % 16) == 0)
> -                               printk("\n");
> -                       printk("%2.2x ", skb->data[i]);
> -               }
> -       }
> -#endif
> -       len = (skblen <= ETH_ZLEN) ? ETH_ZLEN : skblen;
> -       entry = lp->tx_new & lp->tx_ring_mod_mask;
> -       ib->btx_ring[entry].length = (-len) | 0xf000;
> -       ib->btx_ring[entry].misc = 0;
> -
> -       if (skb->len < ETH_ZLEN)
> -               memset((void *)&ib->tx_buf[entry][0], 0, ETH_ZLEN);
> -       skb_copy_from_linear_data(skb, (void *)&ib->tx_buf[entry][0], skblen);
> -
> -       /* Now, give the packet to the lance */
> -       ib->btx_ring[entry].tmd1_bits = (LE_T1_POK|LE_T1_OWN);
> -       lp->tx_new = (lp->tx_new + 1) & lp->tx_ring_mod_mask;
> -
> -       outs++;
> -       /* Kick the lance: transmit now */
> -       WRITERDP(lp, LE_C0_INEA | LE_C0_TDMD);
> -       dev_consume_skb_any(skb);
> -
> -       spin_lock_irqsave(&lp->devlock, flags);
> -       if (TX_BUFFS_AVAIL)
> -               netif_start_queue(dev);
> -       else
> -               lp->tx_full = 1;
> -       spin_unlock_irqrestore(&lp->devlock, flags);
> -
> -       return NETDEV_TX_OK;
> -}
> -EXPORT_SYMBOL_GPL(lance_start_xmit);
> -
> -/* taken from the depca driver via a2065.c */
> -static void lance_load_multicast(struct net_device *dev)
> -{
> -       struct lance_private *lp = netdev_priv(dev);
> -       volatile struct lance_init_block *ib = lp->init_block;
> -       volatile u16 *mcast_table = (u16 *)&ib->filter;
> -       struct netdev_hw_addr *ha;
> -       u32 crc;
> -
> -       /* set all multicast bits */
> -       if (dev->flags & IFF_ALLMULTI) {
> -               ib->filter[0] = 0xffffffff;
> -               ib->filter[1] = 0xffffffff;
> -               return;
> -       }
> -       /* clear the multicast filter */
> -       ib->filter[0] = 0;
> -       ib->filter[1] = 0;
> -
> -       /* Add addresses */
> -       netdev_for_each_mc_addr(ha, dev) {
> -               crc = ether_crc_le(6, ha->addr);
> -               crc = crc >> 26;
> -               mcast_table[crc >> 4] |= 1 << (crc & 0xf);
> -       }
> -}
> -
> -
> -void lance_set_multicast(struct net_device *dev)
> -{
> -       struct lance_private *lp = netdev_priv(dev);
> -       volatile struct lance_init_block *ib = lp->init_block;
> -       int stopped;
> -
> -       stopped = netif_queue_stopped(dev);
> -       if (!stopped)
> -               netif_stop_queue(dev);
> -
> -       while (lp->tx_old != lp->tx_new)
> -               schedule();
> -
> -       WRITERAP(lp, LE_CSR0);
> -       WRITERDP(lp, LE_C0_STOP);
> -       lance_init_ring(dev);
> -
> -       if (dev->flags & IFF_PROMISC) {
> -               ib->mode |= LE_MO_PROM;
> -       } else {
> -               ib->mode &= ~LE_MO_PROM;
> -               lance_load_multicast(dev);
> -       }
> -       load_csrs(lp);
> -       init_restart_lance(lp);
> -
> -       if (!stopped)
> -               netif_start_queue(dev);
> -}
> -EXPORT_SYMBOL_GPL(lance_set_multicast);
> -
> -#ifdef CONFIG_NET_POLL_CONTROLLER
> -void lance_poll(struct net_device *dev)
> -{
> -       struct lance_private *lp = netdev_priv(dev);
> -
> -       spin_lock(&lp->devlock);
> -       WRITERAP(lp, LE_CSR0);
> -       WRITERDP(lp, LE_C0_STRT);
> -       spin_unlock(&lp->devlock);
> -       lance_interrupt(dev->irq, dev);
> -}
> -EXPORT_SYMBOL_GPL(lance_poll);
> -#endif
> -
> -MODULE_DESCRIPTION("LANCE Ethernet IC generic routines");
> -MODULE_LICENSE("GPL");
> diff --git a/drivers/net/ethernet/amd/7990.h b/drivers/net/ethernet/amd/7990.h
> deleted file mode 100644
> index e53551daeea1..000000000000
> --- a/drivers/net/ethernet/amd/7990.h
> +++ /dev/null
> @@ -1,251 +0,0 @@
> -/* SPDX-License-Identifier: GPL-2.0 */
> -/*
> - * 7990.h -- LANCE ethernet IC generic routines.
> - * This is an attempt to separate out the bits of various ethernet
> - * drivers that are common because they all use the AMD 7990 LANCE
> - * (Local Area Network Controller for Ethernet) chip.
> - *
> - * Copyright (C) 05/1998 Peter Maydell <pmaydell@chiark.greenend.org.uk>
> - *
> - * Most of this stuff was obtained by looking at other LANCE drivers,
> - * in particular a2065.[ch]. The AMD C-LANCE datasheet was also helpful.
> - */
> -
> -#ifndef _7990_H
> -#define _7990_H
> -
> -/* The lance only has two register locations. We communicate mostly via memory. */
> -#define LANCE_RDP      0       /* Register Data Port */
> -#define LANCE_RAP      2       /* Register Address Port */
> -
> -/* Transmit/receive ring definitions.
> - * We allow the specific drivers to override these defaults if they want to.
> - * NB: according to lance.c, increasing the number of buffers is a waste
> - * of space and reduces the chance that an upper layer will be able to
> - * reorder queued Tx packets based on priority. [Clearly there is a minimum
> - * limit too: too small and we drop rx packets and can't tx at full speed.]
> - * 4+4 seems to be the usual setting; the atarilance driver uses 3 and 5.
> - */
> -
> -/* Blast! This won't work. The problem is that we can't specify a default
> - * setting because that would cause the lance_init_block struct to be
> - * too long (and overflow the RAM on shared-memory cards like the HP LANCE.
> - */
> -#ifndef LANCE_LOG_TX_BUFFERS
> -#define LANCE_LOG_TX_BUFFERS 1
> -#define LANCE_LOG_RX_BUFFERS 3
> -#endif
> -
> -#define TX_RING_SIZE           (1 << LANCE_LOG_TX_BUFFERS)
> -#define RX_RING_SIZE           (1 << LANCE_LOG_RX_BUFFERS)
> -#define TX_RING_MOD_MASK       (TX_RING_SIZE - 1)
> -#define RX_RING_MOD_MASK       (RX_RING_SIZE - 1)
> -#define TX_RING_LEN_BITS       ((LANCE_LOG_TX_BUFFERS) << 29)
> -#define RX_RING_LEN_BITS       ((LANCE_LOG_RX_BUFFERS) << 29)
> -#define PKT_BUFF_SIZE          (1544)
> -#define RX_BUFF_SIZE           PKT_BUFF_SIZE
> -#define TX_BUFF_SIZE           PKT_BUFF_SIZE
> -
> -/* Each receive buffer is described by a receive message descriptor (RMD) */
> -struct lance_rx_desc {
> -       volatile unsigned short rmd0;       /* low address of packet */
> -       volatile unsigned char  rmd1_bits;  /* descriptor bits */
> -       volatile unsigned char  rmd1_hadr;  /* high address of packet */
> -       volatile short    length;           /* This length is 2s complement (negative)!
> -                                            * Buffer length */
> -       volatile unsigned short mblength;   /* Actual number of bytes received */
> -};
> -
> -/* Ditto for TMD: */
> -struct lance_tx_desc {
> -       volatile unsigned short tmd0;       /* low address of packet */
> -       volatile unsigned char  tmd1_bits;  /* descriptor bits */
> -       volatile unsigned char  tmd1_hadr;  /* high address of packet */
> -       volatile short    length;           /* Length is 2s complement (negative)! */
> -       volatile unsigned short misc;
> -};
> -
> -/* There are three memory structures accessed by the LANCE:
> - * the initialization block, the receive and transmit descriptor rings,
> - * and the data buffers themselves. In fact we might as well put the
> - * init block,the Tx and Rx rings and the buffers together in memory:
> - */
> -struct lance_init_block {
> -       volatile unsigned short mode;           /* Pre-set mode (reg. 15) */
> -       volatile unsigned char phys_addr[6];    /* Physical ethernet address */
> -       volatile unsigned filter[2];            /* Multicast filter (64 bits) */
> -
> -       /* Receive and transmit ring base, along with extra bits. */
> -       volatile unsigned short rx_ptr;         /* receive descriptor addr */
> -       volatile unsigned short rx_len;         /* receive len and high addr */
> -       volatile unsigned short tx_ptr;         /* transmit descriptor addr */
> -       volatile unsigned short tx_len;         /* transmit len and high addr */
> -
> -       /* The Tx and Rx ring entries must be aligned on 8-byte boundaries.
> -        * This will be true if this whole struct is 8-byte aligned.
> -        */
> -       volatile struct lance_tx_desc btx_ring[TX_RING_SIZE];
> -       volatile struct lance_rx_desc brx_ring[RX_RING_SIZE];
> -
> -       volatile char tx_buf[TX_RING_SIZE][TX_BUFF_SIZE];
> -       volatile char rx_buf[RX_RING_SIZE][RX_BUFF_SIZE];
> -       /* we use this just to make the struct big enough that we can move its startaddr
> -        * in order to force alignment to an eight byte boundary.
> -        */
> -};
> -
> -/* This is where we keep all the stuff the driver needs to know about.
> - * I'm definitely unhappy about the mechanism for allowing specific
> - * drivers to add things...
> - */
> -struct lance_private {
> -       const char *name;
> -       unsigned long base;
> -       volatile struct lance_init_block *init_block; /* CPU address of RAM */
> -       volatile struct lance_init_block *lance_init_block; /* LANCE address of RAM */
> -
> -       int rx_new, tx_new;
> -       int rx_old, tx_old;
> -
> -       int lance_log_rx_bufs, lance_log_tx_bufs;
> -       int rx_ring_mod_mask, tx_ring_mod_mask;
> -
> -       int tpe;                        /* TPE is selected */
> -       int auto_select;                /* cable-selection is by carrier */
> -       unsigned short busmaster_regval;
> -
> -       unsigned int irq;               /* IRQ to register */
> -
> -       /* This is because the HP LANCE is disgusting and you have to check
> -        * a DIO-specific register every time you read/write the LANCE regs :-<
> -        * [could we get away with making these some sort of macro?]
> -        */
> -       void (*writerap)(void *, unsigned short);
> -       void (*writerdp)(void *, unsigned short);
> -       unsigned short (*readrdp)(void *);
> -       spinlock_t devlock;
> -       char tx_full;
> -};
> -
> -/*
> - *             Am7990 Control and Status Registers
> - */
> -#define LE_CSR0                0x0000  /* LANCE Controller Status */
> -#define LE_CSR1                0x0001  /* IADR[15:0] (bit0==0 ie word aligned) */
> -#define LE_CSR2                0x0002  /* IADR[23:16] (high bits reserved) */
> -#define LE_CSR3                0x0003  /* Misc */
> -
> -/*
> - *             Bit definitions for CSR0 (LANCE Controller Status)
> - */
> -#define LE_C0_ERR      0x8000  /* Error = BABL | CERR | MISS | MERR */
> -#define LE_C0_BABL     0x4000  /* Babble: Transmitted too many bits */
> -#define LE_C0_CERR     0x2000  /* No Heartbeat (10BASE-T) */
> -#define LE_C0_MISS     0x1000  /* Missed Frame (no rx buffer to put it in) */
> -#define LE_C0_MERR     0x0800  /* Memory Error */
> -#define LE_C0_RINT     0x0400  /* Receive Interrupt */
> -#define LE_C0_TINT     0x0200  /* Transmit Interrupt */
> -#define LE_C0_IDON     0x0100  /* Initialization Done */
> -#define LE_C0_INTR     0x0080  /* Interrupt Flag
> -                                  = BABL | MISS | MERR | RINT | TINT | IDON */
> -#define LE_C0_INEA     0x0040  /* Interrupt Enable */
> -#define LE_C0_RXON     0x0020  /* Receive On */
> -#define LE_C0_TXON     0x0010  /* Transmit On */
> -#define LE_C0_TDMD     0x0008  /* Transmit Demand */
> -#define LE_C0_STOP     0x0004  /* Stop */
> -#define LE_C0_STRT     0x0002  /* Start */
> -#define LE_C0_INIT     0x0001  /* Initialize */
> -
> -
> -/*
> - *             Bit definitions for CSR3
> - */
> -#define LE_C3_BSWP     0x0004  /* Byte Swap (on for big endian byte order) */
> -#define LE_C3_ACON     0x0002  /* ALE Control (on for active low ALE) */
> -#define LE_C3_BCON     0x0001  /* Byte Control */
> -
> -
> -/*
> - *             Mode Flags
> - */
> -#define LE_MO_PROM     0x8000  /* Promiscuous Mode */
> -/* these next ones 0x4000 -- 0x0080 are not available on the LANCE 7990,
> - * but they are in NetBSD's am7990.h, presumably for backwards-compatible chips
> - */
> -#define LE_MO_DRCVBC   0x4000  /* disable receive broadcast */
> -#define LE_MO_DRCVPA   0x2000  /* disable physical address detection */
> -#define LE_MO_DLNKTST  0x1000  /* disable link status */
> -#define LE_MO_DAPC     0x0800  /* disable automatic polarity correction */
> -#define LE_MO_MENDECL  0x0400  /* MENDEC loopback mode */
> -#define LE_MO_LRTTSEL  0x0200  /* lower RX threshold / TX mode selection */
> -#define LE_MO_PSEL1    0x0100  /* port selection bit1 */
> -#define LE_MO_PSEL0    0x0080  /* port selection bit0 */
> -/* and this one is from the C-LANCE data sheet... */
> -#define LE_MO_EMBA     0x0080  /* Enable Modified Backoff Algorithm
> -                                  (C-LANCE, not original LANCE) */
> -#define LE_MO_INTL     0x0040  /* Internal Loopback */
> -#define LE_MO_DRTY     0x0020  /* Disable Retry */
> -#define LE_MO_FCOLL    0x0010  /* Force Collision */
> -#define LE_MO_DXMTFCS  0x0008  /* Disable Transmit CRC */
> -#define LE_MO_LOOP     0x0004  /* Loopback Enable */
> -#define LE_MO_DTX      0x0002  /* Disable Transmitter */
> -#define LE_MO_DRX      0x0001  /* Disable Receiver */
> -
> -
> -/*
> - *             Receive Flags
> - */
> -#define LE_R1_OWN      0x80    /* LANCE owns the descriptor */
> -#define LE_R1_ERR      0x40    /* Error */
> -#define LE_R1_FRA      0x20    /* Framing Error */
> -#define LE_R1_OFL      0x10    /* Overflow Error */
> -#define LE_R1_CRC      0x08    /* CRC Error */
> -#define LE_R1_BUF      0x04    /* Buffer Error */
> -#define LE_R1_SOP      0x02    /* Start of Packet */
> -#define LE_R1_EOP      0x01    /* End of Packet */
> -#define LE_R1_POK      0x03    /* Packet is complete: SOP + EOP */
> -
> -
> -/*
> - *             Transmit Flags
> - */
> -#define LE_T1_OWN      0x80    /* LANCE owns the descriptor */
> -#define LE_T1_ERR      0x40    /* Error */
> -#define LE_T1_RES      0x20    /* Reserved, LANCE writes this with a zero */
> -#define LE_T1_EMORE    0x10    /* More than one retry needed */
> -#define LE_T1_EONE     0x08    /* One retry needed */
> -#define LE_T1_EDEF     0x04    /* Deferred */
> -#define LE_T1_SOP      0x02    /* Start of Packet */
> -#define LE_T1_EOP      0x01    /* End of Packet */
> -#define LE_T1_POK      0x03    /* Packet is complete: SOP + EOP */
> -
> -/*
> - *             Error Flags
> - */
> -#define LE_T3_BUF      0x8000  /* Buffer Error */
> -#define LE_T3_UFL      0x4000  /* Underflow Error */
> -#define LE_T3_LCOL     0x1000  /* Late Collision */
> -#define LE_T3_CLOS     0x0800  /* Loss of Carrier */
> -#define LE_T3_RTY      0x0400  /* Retry Error */
> -#define LE_T3_TDR      0x03ff  /* Time Domain Reflectometry */
> -
> -/* Miscellaneous useful macros */
> -
> -#define TX_BUFFS_AVAIL ((lp->tx_old <= lp->tx_new) ? \
> -                       lp->tx_old + lp->tx_ring_mod_mask - lp->tx_new : \
> -                       lp->tx_old - lp->tx_new - 1)
> -
> -/* The LANCE only uses 24 bit addresses. This does the obvious thing. */
> -#define LANCE_ADDR(x) ((int)(x) & ~0xff000000)
> -
> -/* Now the prototypes we export */
> -int lance_open(struct net_device *dev);
> -int lance_close(struct net_device *dev);
> -netdev_tx_t lance_start_xmit(struct sk_buff *skb, struct net_device *dev);
> -void lance_set_multicast(struct net_device *dev);
> -void lance_tx_timeout(struct net_device *dev, unsigned int txqueue);
> -#ifdef CONFIG_NET_POLL_CONTROLLER
> -void lance_poll(struct net_device *dev);
> -#endif
> -
> -#endif /* ndef _7990_H */
> diff --git a/drivers/net/ethernet/amd/Kconfig b/drivers/net/ethernet/amd/Kconfig
> index 45e8d698781c..9e83f3aa435a 100644
> --- a/drivers/net/ethernet/amd/Kconfig
> +++ b/drivers/net/ethernet/amd/Kconfig
> @@ -93,14 +93,6 @@ config DECLANCE
>           DEC (now Compaq) based on the AMD LANCE chipset, including the
>           DEPCA series.  (This chipset is better known via the NE2100 cards.)
>
> -config HPLANCE
> -       tristate "HP on-board LANCE support"
> -       depends on DIO
> -       select CRC32
> -       help
> -         If you want to use the builtin "LANCE" Ethernet controller on an
> -         HP300 machine, say Y here.
> -
>  config MIPS_AU1X00_ENET
>         tristate "MIPS AU1000 Ethernet support"
>         depends on MIPS_ALCHEMY
> @@ -110,16 +102,6 @@ config MIPS_AU1X00_ENET
>           If you have an Alchemy Semi AU1X00 based system
>           say Y.  Otherwise, say N.
>
> -config MVME147_NET
> -       tristate "MVME147 (LANCE) Ethernet support"
> -       depends on MVME147
> -       select CRC32
> -       help
> -         Support for the on-board Ethernet interface on the Motorola MVME147
> -         single-board computer.  Say Y here to include the
> -         driver for this chip in your kernel.
> -         To compile this driver as a module, choose M here.
> -
>  config PCMCIA_NMCLAN
>         tristate "New Media PCMCIA support"
>         depends on PCMCIA && HAS_IOPORT
> diff --git a/drivers/net/ethernet/amd/Makefile b/drivers/net/ethernet/amd/Makefile
> index 2dcfb84731e1..387ec74e8e95 100644
> --- a/drivers/net/ethernet/amd/Makefile
> +++ b/drivers/net/ethernet/amd/Makefile
> @@ -8,10 +8,8 @@ obj-$(CONFIG_AMD8111_ETH) += amd8111e.o
>  obj-$(CONFIG_ARIADNE) += ariadne.o
>  obj-$(CONFIG_ATARILANCE) += atarilance.o
>  obj-$(CONFIG_DECLANCE) += declance.o
> -obj-$(CONFIG_HPLANCE) += hplance.o 7990.o
>  obj-$(CONFIG_LANCE) += lance.o
>  obj-$(CONFIG_MIPS_AU1X00_ENET) += au1000_eth.o
> -obj-$(CONFIG_MVME147_NET) += mvme147.o 7990.o
>  obj-$(CONFIG_PCMCIA_NMCLAN) += nmclan_cs.o
>  obj-$(CONFIG_PCNET32) += pcnet32.o
>  obj-$(CONFIG_SUN3LANCE) += sun3lance.o
> diff --git a/drivers/net/ethernet/amd/hplance.c b/drivers/net/ethernet/amd/hplance.c
> deleted file mode 100644
> index df42294530cb..000000000000
> --- a/drivers/net/ethernet/amd/hplance.c
> +++ /dev/null
> @@ -1,238 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0-only
> -/* hplance.c  : the  Linux/hp300/lance ethernet driver
> - *
> - * Copyright (C) 05/1998 Peter Maydell <pmaydell@chiark.greenend.org.uk>
> - * Based on the Sun Lance driver and the NetBSD HP Lance driver
> - * Uses the generic 7990.c LANCE code.
> - */
> -
> -#include <linux/module.h>
> -#include <linux/kernel.h>
> -#include <linux/types.h>
> -#include <linux/interrupt.h>
> -#include <linux/ioport.h>
> -#include <linux/string.h>
> -#include <linux/delay.h>
> -#include <linux/init.h>
> -#include <linux/errno.h>
> -#include <linux/pgtable.h>
> -/* Used for the temporal inet entries and routing */
> -#include <linux/socket.h>
> -#include <linux/route.h>
> -#include <linux/dio.h>
> -#include <linux/netdevice.h>
> -#include <linux/etherdevice.h>
> -#include <linux/skbuff.h>
> -
> -#include <asm/io.h>
> -
> -#include "hplance.h"
> -
> -/* We have 16392 bytes of RAM for the init block and buffers. This places
> - * an upper limit on the number of buffers we can use. NetBSD uses 8 Rx
> - * buffers and 2 Tx buffers, it takes (8 + 2) * 1544 bytes.
> - */
> -#define LANCE_LOG_TX_BUFFERS 1
> -#define LANCE_LOG_RX_BUFFERS 3
> -
> -#include "7990.h"                                 /* use generic LANCE code */
> -
> -/* Our private data structure */
> -struct hplance_private {
> -       struct lance_private lance;
> -};
> -
> -/* function prototypes... This is easy because all the grot is in the
> - * generic LANCE support. All we have to support is probing for boards,
> - * plus board-specific init, open and close actions.
> - * Oh, and we need to tell the generic code how to read and write LANCE registers...
> - */
> -static int hplance_init_one(struct dio_dev *d, const struct dio_device_id *ent);
> -static void hplance_init(struct net_device *dev, struct dio_dev *d);
> -static void hplance_remove_one(struct dio_dev *d);
> -static void hplance_writerap(void *priv, unsigned short value);
> -static void hplance_writerdp(void *priv, unsigned short value);
> -static unsigned short hplance_readrdp(void *priv);
> -static int hplance_open(struct net_device *dev);
> -static int hplance_close(struct net_device *dev);
> -
> -static struct dio_device_id hplance_dio_tbl[] = {
> -       { DIO_ID_LAN },
> -       { 0 }
> -};
> -
> -static struct dio_driver hplance_driver = {
> -       .name      = "hplance",
> -       .id_table  = hplance_dio_tbl,
> -       .probe     = hplance_init_one,
> -       .remove    = hplance_remove_one,
> -};
> -
> -static const struct net_device_ops hplance_netdev_ops = {
> -       .ndo_open               = hplance_open,
> -       .ndo_stop               = hplance_close,
> -       .ndo_start_xmit         = lance_start_xmit,
> -       .ndo_set_rx_mode        = lance_set_multicast,
> -       .ndo_validate_addr      = eth_validate_addr,
> -       .ndo_set_mac_address    = eth_mac_addr,
> -#ifdef CONFIG_NET_POLL_CONTROLLER
> -       .ndo_poll_controller    = lance_poll,
> -#endif
> -};
> -
> -/* Find all the HP Lance boards and initialise them... */
> -static int hplance_init_one(struct dio_dev *d, const struct dio_device_id *ent)
> -{
> -       struct net_device *dev;
> -       int err = -ENOMEM;
> -
> -       dev = alloc_etherdev(sizeof(struct hplance_private));
> -       if (!dev)
> -               goto out;
> -
> -       err = -EBUSY;
> -       if (!request_mem_region(dio_resource_start(d),
> -                               dio_resource_len(d), d->name))
> -               goto out_free_netdev;
> -
> -       hplance_init(dev, d);
> -       err = register_netdev(dev);
> -       if (err)
> -               goto out_release_mem_region;
> -
> -       dio_set_drvdata(d, dev);
> -
> -       printk(KERN_INFO "%s: %s; select code %d, addr %pM, irq %d\n",
> -              dev->name, d->name, d->scode, dev->dev_addr, d->ipl);
> -
> -       return 0;
> -
> - out_release_mem_region:
> -       release_mem_region(dio_resource_start(d), dio_resource_len(d));
> - out_free_netdev:
> -       free_netdev(dev);
> - out:
> -       return err;
> -}
> -
> -static void hplance_remove_one(struct dio_dev *d)
> -{
> -       struct net_device *dev = dio_get_drvdata(d);
> -
> -       unregister_netdev(dev);
> -       release_mem_region(dio_resource_start(d), dio_resource_len(d));
> -       free_netdev(dev);
> -}
> -
> -/* Initialise a single lance board at the given DIO device */
> -static void hplance_init(struct net_device *dev, struct dio_dev *d)
> -{
> -       unsigned long va = (d->resource.start + DIO_VIRADDRBASE);
> -       struct hplance_private *lp;
> -       u8 addr[ETH_ALEN];
> -       int i;
> -
> -       /* reset the board */
> -       out_8(va + DIO_IDOFF, 0xff);
> -       udelay(100);                              /* ariba! ariba! udelay! udelay! */
> -
> -       /* Fill the dev fields */
> -       dev->base_addr = va;
> -       dev->netdev_ops = &hplance_netdev_ops;
> -       dev->dma = 0;
> -
> -       for (i = 0; i < 6; i++) {
> -               /* The NVRAM holds our ethernet address, one nibble per byte,
> -                * at bytes NVRAMOFF+1,3,5,7,9...
> -                */
> -               addr[i] = ((in_8(va + HPLANCE_NVRAMOFF + i*4 + 1) & 0xF) << 4)
> -                       | (in_8(va + HPLANCE_NVRAMOFF + i*4 + 3) & 0xF);
> -       }
> -       eth_hw_addr_set(dev, addr);
> -
> -       lp = netdev_priv(dev);
> -       lp->lance.name = d->name;
> -       lp->lance.base = va;
> -       lp->lance.init_block = (struct lance_init_block *)(va + HPLANCE_MEMOFF); /* CPU addr */
> -       lp->lance.lance_init_block = NULL;              /* LANCE addr of same RAM */
> -       lp->lance.busmaster_regval = LE_C3_BSWP;        /* we're bigendian */
> -       lp->lance.irq = d->ipl;
> -       lp->lance.writerap = hplance_writerap;
> -       lp->lance.writerdp = hplance_writerdp;
> -       lp->lance.readrdp = hplance_readrdp;
> -       lp->lance.lance_log_rx_bufs = LANCE_LOG_RX_BUFFERS;
> -       lp->lance.lance_log_tx_bufs = LANCE_LOG_TX_BUFFERS;
> -       lp->lance.rx_ring_mod_mask = RX_RING_MOD_MASK;
> -       lp->lance.tx_ring_mod_mask = TX_RING_MOD_MASK;
> -}
> -
> -/* This is disgusting. We have to check the DIO status register for ack every
> - * time we read or write the LANCE registers.
> - */
> -static void hplance_writerap(void *priv, unsigned short value)
> -{
> -       struct lance_private *lp = (struct lance_private *)priv;
> -
> -       do {
> -               out_be16(lp->base + HPLANCE_REGOFF + LANCE_RAP, value);
> -       } while ((in_8(lp->base + HPLANCE_STATUS) & LE_ACK) == 0);
> -}
> -
> -static void hplance_writerdp(void *priv, unsigned short value)
> -{
> -       struct lance_private *lp = (struct lance_private *)priv;
> -
> -       do {
> -               out_be16(lp->base + HPLANCE_REGOFF + LANCE_RDP, value);
> -       } while ((in_8(lp->base + HPLANCE_STATUS) & LE_ACK) == 0);
> -}
> -
> -static unsigned short hplance_readrdp(void *priv)
> -{
> -       struct lance_private *lp = (struct lance_private *)priv;
> -       __u16 value;
> -
> -       do {
> -               value = in_be16(lp->base + HPLANCE_REGOFF + LANCE_RDP);
> -       } while ((in_8(lp->base + HPLANCE_STATUS) & LE_ACK) == 0);
> -       return value;
> -}
> -
> -static int hplance_open(struct net_device *dev)
> -{
> -       int status;
> -       struct lance_private *lp = netdev_priv(dev);
> -
> -       status = lance_open(dev);                 /* call generic lance open code */
> -       if (status)
> -               return status;
> -       /* enable interrupts at board level. */
> -       out_8(lp->base + HPLANCE_STATUS, LE_IE);
> -
> -       return 0;
> -}
> -
> -static int hplance_close(struct net_device *dev)
> -{
> -       struct lance_private *lp = netdev_priv(dev);
> -
> -       out_8(lp->base + HPLANCE_STATUS, 0);    /* disable interrupts at boardlevel */
> -       lance_close(dev);
> -       return 0;
> -}
> -
> -static int __init hplance_init_module(void)
> -{
> -       return dio_register_driver(&hplance_driver);
> -}
> -
> -static void __exit hplance_cleanup_module(void)
> -{
> -       dio_unregister_driver(&hplance_driver);
> -}
> -
> -module_init(hplance_init_module);
> -module_exit(hplance_cleanup_module);
> -
> -MODULE_DESCRIPTION("HP300 on-board LANCE Ethernet driver");
> -MODULE_LICENSE("GPL");
> diff --git a/drivers/net/ethernet/amd/hplance.h b/drivers/net/ethernet/amd/hplance.h
> deleted file mode 100644
> index bc845a2c60c1..000000000000
> --- a/drivers/net/ethernet/amd/hplance.h
> +++ /dev/null
> @@ -1,27 +0,0 @@
> -/* SPDX-License-Identifier: GPL-2.0 */
> -/* Random defines and structures for the HP Lance driver.
> - * Copyright (C) 05/1998 Peter Maydell <pmaydell@chiark.greenend.org.uk>
> - * Based on the Sun Lance driver and the NetBSD HP Lance driver
> - */
> -
> -/* Registers */
> -#define HPLANCE_ID             0x01            /* DIO register: ID byte */
> -#define HPLANCE_STATUS         0x03            /* DIO register: interrupt enable/status */
> -
> -/* Control and status bits for the status register */
> -#define LE_IE 0x80                                /* interrupt enable */
> -#define LE_IR 0x40                                /* interrupt requested */
> -#define LE_LOCK 0x08                              /* lock status register */
> -#define LE_ACK 0x04                               /* ack of lock */
> -#define LE_JAB 0x02                               /* loss of tx clock (???) */
> -/* We can also extract the IPL from the status register with the standard
> - * DIO_IPL(hplance) macro, or using dio_scodetoipl()
> - */
> -
> -/* These are the offsets for the DIO regs (hplance_reg), lance_ioreg,
> - * memory and NVRAM:
> - */
> -#define HPLANCE_IDOFF 0                           /* board baseaddr */
> -#define HPLANCE_REGOFF 0x4000                     /* lance registers */
> -#define HPLANCE_MEMOFF 0x8000                     /* struct lance_init_block */
> -#define HPLANCE_NVRAMOFF 0xC008                   /* etheraddress as one *nibble* per byte */
> diff --git a/drivers/net/ethernet/amd/mvme147.c b/drivers/net/ethernet/amd/mvme147.c
> deleted file mode 100644
> index f19b04b92fa9..000000000000
> --- a/drivers/net/ethernet/amd/mvme147.c
> +++ /dev/null
> @@ -1,198 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0-only
> -/* mvme147.c  : the  Linux/mvme147/lance ethernet driver
> - *
> - * Copyright (C) 05/1998 Peter Maydell <pmaydell@chiark.greenend.org.uk>
> - * Based on the Sun Lance driver and the NetBSD HP Lance driver
> - * Uses the generic 7990.c LANCE code.
> - */
> -
> -#include <linux/module.h>
> -#include <linux/kernel.h>
> -#include <linux/types.h>
> -#include <linux/interrupt.h>
> -#include <linux/ioport.h>
> -#include <linux/string.h>
> -#include <linux/delay.h>
> -#include <linux/init.h>
> -#include <linux/errno.h>
> -#include <linux/gfp.h>
> -#include <linux/pgtable.h>
> -/* Used for the temporal inet entries and routing */
> -#include <linux/socket.h>
> -#include <linux/route.h>
> -#include <linux/netdevice.h>
> -#include <linux/etherdevice.h>
> -#include <linux/skbuff.h>
> -
> -#include <asm/io.h>
> -#include <asm/mvme147hw.h>
> -
> -/* We have 32K of RAM for the init block and buffers. This places
> - * an upper limit on the number of buffers we can use. NetBSD uses 8 Rx
> - * buffers and 2 Tx buffers, it takes (8 + 2) * 1544 bytes.
> - */
> -#define LANCE_LOG_TX_BUFFERS 1
> -#define LANCE_LOG_RX_BUFFERS 3
> -
> -#include "7990.h"                                 /* use generic LANCE code */
> -
> -/* Our private data structure */
> -struct m147lance_private {
> -       struct lance_private lance;
> -       unsigned long ram;
> -};
> -
> -/* function prototypes... This is easy because all the grot is in the
> - * generic LANCE support. All we have to support is probing for boards,
> - * plus board-specific init, open and close actions.
> - * Oh, and we need to tell the generic code how to read and write LANCE registers...
> - */
> -static int m147lance_open(struct net_device *dev);
> -static int m147lance_close(struct net_device *dev);
> -static void m147lance_writerap(struct lance_private *lp, unsigned short value);
> -static void m147lance_writerdp(struct lance_private *lp, unsigned short value);
> -static unsigned short m147lance_readrdp(struct lance_private *lp);
> -
> -typedef void (*writerap_t)(void *, unsigned short);
> -typedef void (*writerdp_t)(void *, unsigned short);
> -typedef unsigned short (*readrdp_t)(void *);
> -
> -static const struct net_device_ops lance_netdev_ops = {
> -       .ndo_open               = m147lance_open,
> -       .ndo_stop               = m147lance_close,
> -       .ndo_start_xmit         = lance_start_xmit,
> -       .ndo_set_rx_mode        = lance_set_multicast,
> -       .ndo_tx_timeout         = lance_tx_timeout,
> -       .ndo_validate_addr      = eth_validate_addr,
> -       .ndo_set_mac_address    = eth_mac_addr,
> -};
> -
> -/* Initialise the one and only on-board 7990 */
> -static struct net_device * __init mvme147lance_probe(void)
> -{
> -       struct net_device *dev;
> -       static int called;
> -       static const char name[] = "MVME147 LANCE";
> -       struct m147lance_private *lp;
> -       u8 macaddr[ETH_ALEN];
> -       u_long *addr;
> -       u_long address;
> -       int err;
> -
> -       if (!MACH_IS_MVME147 || called)
> -               return ERR_PTR(-ENODEV);
> -       called++;
> -
> -       dev = alloc_etherdev(sizeof(struct m147lance_private));
> -       if (!dev)
> -               return ERR_PTR(-ENOMEM);
> -
> -       /* Fill the dev fields */
> -       dev->base_addr = (unsigned long)MVME147_LANCE_BASE;
> -       dev->netdev_ops = &lance_netdev_ops;
> -       dev->dma = 0;
> -
> -       addr = (u_long *)ETHERNET_ADDRESS;
> -       address = *addr;
> -       macaddr[0] = 0x08;
> -       macaddr[1] = 0x00;
> -       macaddr[2] = 0x3e;
> -       address = address >> 8;
> -       macaddr[5] = address&0xff;
> -       address = address >> 8;
> -       macaddr[4] = address&0xff;
> -       address = address >> 8;
> -       macaddr[3] = address&0xff;
> -       eth_hw_addr_set(dev, macaddr);
> -
> -       lp = netdev_priv(dev);
> -       lp->ram = __get_dma_pages(GFP_ATOMIC, 3);       /* 32K */
> -       if (!lp->ram) {
> -               printk("%s: No memory for LANCE buffers\n", dev->name);
> -               free_netdev(dev);
> -               return ERR_PTR(-ENOMEM);
> -       }
> -
> -       lp->lance.name = name;
> -       lp->lance.base = dev->base_addr;
> -       lp->lance.init_block = (struct lance_init_block *)(lp->ram); /* CPU addr */
> -       lp->lance.lance_init_block = (struct lance_init_block *)(lp->ram);                 /* LANCE addr of same RAM */
> -       lp->lance.busmaster_regval = LE_C3_BSWP;        /* we're bigendian */
> -       lp->lance.irq = MVME147_LANCE_IRQ;
> -       lp->lance.writerap = (writerap_t)m147lance_writerap;
> -       lp->lance.writerdp = (writerdp_t)m147lance_writerdp;
> -       lp->lance.readrdp = (readrdp_t)m147lance_readrdp;
> -       lp->lance.lance_log_rx_bufs = LANCE_LOG_RX_BUFFERS;
> -       lp->lance.lance_log_tx_bufs = LANCE_LOG_TX_BUFFERS;
> -       lp->lance.rx_ring_mod_mask = RX_RING_MOD_MASK;
> -       lp->lance.tx_ring_mod_mask = TX_RING_MOD_MASK;
> -
> -       err = register_netdev(dev);
> -       if (err) {
> -               free_pages(lp->ram, 3);
> -               free_netdev(dev);
> -               return ERR_PTR(err);
> -       }
> -
> -       netdev_info(dev, "MVME147 at 0x%08lx, irq %d, Hardware Address %pM\n",
> -                   dev->base_addr, MVME147_LANCE_IRQ, dev->dev_addr);
> -
> -       return dev;
> -}
> -
> -static void m147lance_writerap(struct lance_private *lp, unsigned short value)
> -{
> -       out_be16(lp->base + LANCE_RAP, value);
> -}
> -
> -static void m147lance_writerdp(struct lance_private *lp, unsigned short value)
> -{
> -       out_be16(lp->base + LANCE_RDP, value);
> -}
> -
> -static unsigned short m147lance_readrdp(struct lance_private *lp)
> -{
> -       return in_be16(lp->base + LANCE_RDP);
> -}
> -
> -static int m147lance_open(struct net_device *dev)
> -{
> -       int status;
> -
> -       status = lance_open(dev);                 /* call generic lance open code */
> -       if (status)
> -               return status;
> -       /* enable interrupts at board level. */
> -       m147_pcc->lan_cntrl = 0;       /* clear the interrupts (if any) */
> -       m147_pcc->lan_cntrl = 0x08 | 0x04;     /* Enable irq 4 */
> -
> -       return 0;
> -}
> -
> -static int m147lance_close(struct net_device *dev)
> -{
> -       /* disable interrupts at boardlevel */
> -       m147_pcc->lan_cntrl = 0x0; /* disable interrupts */
> -       lance_close(dev);
> -       return 0;
> -}
> -
> -MODULE_DESCRIPTION("MVME147 LANCE Ethernet driver");
> -MODULE_LICENSE("GPL");
> -
> -static struct net_device *dev_mvme147_lance;
> -static int __init m147lance_init(void)
> -{
> -       dev_mvme147_lance = mvme147lance_probe();
> -       return PTR_ERR_OR_ZERO(dev_mvme147_lance);
> -}
> -module_init(m147lance_init);
> -
> -static void __exit m147lance_exit(void)
> -{
> -       struct m147lance_private *lp = netdev_priv(dev_mvme147_lance);
> -       unregister_netdev(dev_mvme147_lance);
> -       free_pages(lp->ram, 3);
> -       free_netdev(dev_mvme147_lance);
> -}
> -module_exit(m147lance_exit);
>
> --
> 2.53.0
>
>

^ permalink raw reply

* Re: [PATCH net 12/18] drivers: net: cirrus: mac89x0: Remove this driver
From: Geert Uytterhoeven @ 2026-04-22  7:36 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Simon Horman, Jonathan Corbet, Shuah Khan,
	linux-kernel, netdev, linux-doc, linux-m68k
In-Reply-To: <20260421-v7-0-0-net-next-driver-removal-v1-v1-12-69517c689d1f@lunn.ch>

CC linux-m68k

On Wed, 22 Apr 2026 at 02:48, Andrew Lunn <andrew@lunn.ch> wrote:
>
> The mac89x0 was written by Russell Nelson in 1996. It is an MAC
> device, so unlikely to be used with modern kernels.
>
> Signed-off-by: Andrew Lunn <andrew@lunn.ch>
> ---
>  drivers/net/ethernet/cirrus/Kconfig   |  10 -
>  drivers/net/ethernet/cirrus/Makefile  |   1 -
>  drivers/net/ethernet/cirrus/cs89x0.h  | 461 ---------------------------
>  drivers/net/ethernet/cirrus/mac89x0.c | 577 ----------------------------------
>  4 files changed, 1049 deletions(-)
>
> diff --git a/drivers/net/ethernet/cirrus/Kconfig b/drivers/net/ethernet/cirrus/Kconfig
> index 1a0c7b3bfcd6..786d379e79fe 100644
> --- a/drivers/net/ethernet/cirrus/Kconfig
> +++ b/drivers/net/ethernet/cirrus/Kconfig
> @@ -25,14 +25,4 @@ config EP93XX_ETH
>           This is a driver for the ethernet hardware included in EP93xx CPUs.
>           Say Y if you are building a kernel for EP93xx based devices.
>
> -config MAC89x0
> -       tristate "Macintosh CS89x0 based ethernet cards"
> -       depends on MAC
> -       help
> -         Support for CS89x0 chipset based Ethernet cards.  If you have a
> -         Nubus or LC-PDS network (Ethernet) card of this type, say Y here.
> -
> -         To compile this driver as a module, choose M here. This module will
> -         be called mac89x0.
> -
>  endif # NET_VENDOR_CIRRUS
> diff --git a/drivers/net/ethernet/cirrus/Makefile b/drivers/net/ethernet/cirrus/Makefile
> index cb740939d976..03800af0f0e1 100644
> --- a/drivers/net/ethernet/cirrus/Makefile
> +++ b/drivers/net/ethernet/cirrus/Makefile
> @@ -4,4 +4,3 @@
>  #
>
>  obj-$(CONFIG_EP93XX_ETH) += ep93xx_eth.o
> -obj-$(CONFIG_MAC89x0) += mac89x0.o
> diff --git a/drivers/net/ethernet/cirrus/cs89x0.h b/drivers/net/ethernet/cirrus/cs89x0.h
> deleted file mode 100644
> index 210f9ec9af4b..000000000000
> --- a/drivers/net/ethernet/cirrus/cs89x0.h
> +++ /dev/null
> @@ -1,461 +0,0 @@
> -/*  Copyright, 1988-1992, Russell Nelson, Crynwr Software
> -
> -   This program is free software; you can redistribute it and/or modify
> -   it under the terms of the GNU General Public License as published by
> -   the Free Software Foundation, version 1.
> -
> -   This program is distributed in the hope that it will be useful,
> -   but WITHOUT ANY WARRANTY; without even the implied warranty of
> -   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> -   GNU General Public License for more details.
> -
> -   You should have received a copy of the GNU General Public License
> -   along with this program; if not, write to the Free Software
> -   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
> -   */
> -
> -
> -#define PP_ChipID 0x0000       /* offset   0h -> Corp -ID              */
> -                               /* offset   2h -> Model/Product Number  */
> -                               /* offset   3h -> Chip Revision Number  */
> -
> -#define PP_ISAIOB 0x0020       /*  IO base address */
> -#define PP_CS8900_ISAINT 0x0022        /*  ISA interrupt select */
> -#define PP_CS8920_ISAINT 0x0370        /*  ISA interrupt select */
> -#define PP_CS8900_ISADMA 0x0024        /*  ISA Rec DMA channel */
> -#define PP_CS8920_ISADMA 0x0374        /*  ISA Rec DMA channel */
> -#define PP_ISASOF 0x0026       /*  ISA DMA offset */
> -#define PP_DmaFrameCnt 0x0028  /*  ISA DMA Frame count */
> -#define PP_DmaByteCnt 0x002A   /*  ISA DMA Byte count */
> -#define PP_CS8900_ISAMemB 0x002C       /*  Memory base */
> -#define PP_CS8920_ISAMemB 0x0348 /*  */
> -
> -#define PP_ISABootBase 0x0030  /*  Boot Prom base  */
> -#define PP_ISABootMask 0x0034  /*  Boot Prom Mask */
> -
> -/* EEPROM data and command registers */
> -#define PP_EECMD 0x0040                /*  NVR Interface Command register */
> -#define PP_EEData 0x0042       /*  NVR Interface Data Register */
> -#define PP_DebugReg 0x0044     /*  Debug Register */
> -
> -#define PP_RxCFG 0x0102                /*  Rx Bus config */
> -#define PP_RxCTL 0x0104                /*  Receive Control Register */
> -#define PP_TxCFG 0x0106                /*  Transmit Config Register */
> -#define PP_TxCMD 0x0108                /*  Transmit Command Register */
> -#define PP_BufCFG 0x010A       /*  Bus configuration Register */
> -#define PP_LineCTL 0x0112      /*  Line Config Register */
> -#define PP_SelfCTL 0x0114      /*  Self Command Register */
> -#define PP_BusCTL 0x0116       /*  ISA bus control Register */
> -#define PP_TestCTL 0x0118      /*  Test Register */
> -#define PP_AutoNegCTL 0x011C   /*  Auto Negotiation Ctrl */
> -
> -#define PP_ISQ 0x0120          /*  Interrupt Status */
> -#define PP_RxEvent 0x0124      /*  Rx Event Register */
> -#define PP_TxEvent 0x0128      /*  Tx Event Register */
> -#define PP_BufEvent 0x012C     /*  Bus Event Register */
> -#define PP_RxMiss 0x0130       /*  Receive Miss Count */
> -#define PP_TxCol 0x0132                /*  Transmit Collision Count */
> -#define PP_LineST 0x0134       /*  Line State Register */
> -#define PP_SelfST 0x0136       /*  Self State register */
> -#define PP_BusST 0x0138                /*  Bus Status */
> -#define PP_TDR 0x013C          /*  Time Domain Reflectometry */
> -#define PP_AutoNegST 0x013E    /*  Auto Neg Status */
> -#define PP_TxCommand 0x0144    /*  Tx Command */
> -#define PP_TxLength 0x0146     /*  Tx Length */
> -#define PP_LAF 0x0150          /*  Hash Table */
> -#define PP_IA 0x0158           /*  Physical Address Register */
> -
> -#define PP_RxStatus 0x0400     /*  Receive start of frame */
> -#define PP_RxLength 0x0402     /*  Receive Length of frame */
> -#define PP_RxFrame 0x0404      /*  Receive frame pointer */
> -#define PP_TxFrame 0x0A00      /*  Transmit frame pointer */
> -
> -/*  Primary I/O Base Address. If no I/O base is supplied by the user, then this */
> -/*  can be used as the default I/O base to access the PacketPage Area. */
> -#define DEFAULTIOBASE 0x0300
> -#define FIRST_IO 0x020C                /*  First I/O port to check */
> -#define LAST_IO 0x037C         /*  Last I/O port to check (+10h) */
> -#define ADD_MASK 0x3000                /*  Mask it use of the ADD_PORT register */
> -#define ADD_SIG 0x3000         /*  Expected ID signature */
> -
> -/* On Macs, we only need use the ISA I/O stuff until we do MEMORY_ON */
> -#ifdef CONFIG_MAC
> -#define LCSLOTBASE 0xfee00000
> -#define MMIOBASE 0x40000
> -#endif
> -
> -#define CHIP_EISA_ID_SIG 0x630E   /*  Product ID Code for Crystal Chip (CS8900 spec 4.3) */
> -#define CHIP_EISA_ID_SIG_STR "0x630E"
> -
> -#ifdef IBMEIPKT
> -#define EISA_ID_SIG 0x4D24     /*  IBM */
> -#define PART_NO_SIG 0x1010     /*  IBM */
> -#define MONGOOSE_BIT 0x0000    /*  IBM */
> -#else
> -#define EISA_ID_SIG 0x630E     /*  PnP Vendor ID (same as chip id for Crystal board) */
> -#define PART_NO_SIG 0x4000     /*  ID code CS8920 board (PnP Vendor Product code) */
> -#define MONGOOSE_BIT 0x2000    /*  PART_NO_SIG + MONGOOSE_BUT => ID of mongoose */
> -#endif
> -
> -#define PRODUCT_ID_ADD 0x0002   /*  Address of product ID */
> -
> -/*  Mask to find out the types of  registers */
> -#define REG_TYPE_MASK 0x001F
> -
> -/*  Eeprom Commands */
> -#define ERSE_WR_ENBL 0x00F0
> -#define ERSE_WR_DISABLE 0x0000
> -
> -/*  Defines Control/Config register quintuplet numbers */
> -#define RX_BUF_CFG 0x0003
> -#define RX_CONTROL 0x0005
> -#define TX_CFG 0x0007
> -#define TX_COMMAND 0x0009
> -#define BUF_CFG 0x000B
> -#define LINE_CONTROL 0x0013
> -#define SELF_CONTROL 0x0015
> -#define BUS_CONTROL 0x0017
> -#define TEST_CONTROL 0x0019
> -
> -/*  Defines Status/Count registers quintuplet numbers */
> -#define RX_EVENT 0x0004
> -#define TX_EVENT 0x0008
> -#define BUF_EVENT 0x000C
> -#define RX_MISS_COUNT 0x0010
> -#define TX_COL_COUNT 0x0012
> -#define LINE_STATUS 0x0014
> -#define SELF_STATUS 0x0016
> -#define BUS_STATUS 0x0018
> -#define TDR 0x001C
> -
> -/* PP_RxCFG - Receive  Configuration and Interrupt Mask bit definition -  Read/write */
> -#define SKIP_1 0x0040
> -#define RX_STREAM_ENBL 0x0080
> -#define RX_OK_ENBL 0x0100
> -#define RX_DMA_ONLY 0x0200
> -#define AUTO_RX_DMA 0x0400
> -#define BUFFER_CRC 0x0800
> -#define RX_CRC_ERROR_ENBL 0x1000
> -#define RX_RUNT_ENBL 0x2000
> -#define RX_EXTRA_DATA_ENBL 0x4000
> -
> -/* PP_RxCTL - Receive Control bit definition - Read/write */
> -#define RX_IA_HASH_ACCEPT 0x0040
> -#define RX_PROM_ACCEPT 0x0080
> -#define RX_OK_ACCEPT 0x0100
> -#define RX_MULTCAST_ACCEPT 0x0200
> -#define RX_IA_ACCEPT 0x0400
> -#define RX_BROADCAST_ACCEPT 0x0800
> -#define RX_BAD_CRC_ACCEPT 0x1000
> -#define RX_RUNT_ACCEPT 0x2000
> -#define RX_EXTRA_DATA_ACCEPT 0x4000
> -#define RX_ALL_ACCEPT (RX_PROM_ACCEPT|RX_BAD_CRC_ACCEPT|RX_RUNT_ACCEPT|RX_EXTRA_DATA_ACCEPT)
> -/*  Default receive mode - individually addressed, broadcast, and error free */
> -#define DEF_RX_ACCEPT (RX_IA_ACCEPT | RX_BROADCAST_ACCEPT | RX_OK_ACCEPT)
> -
> -/* PP_TxCFG - Transmit Configuration Interrupt Mask bit definition - Read/write */
> -#define TX_LOST_CRS_ENBL 0x0040
> -#define TX_SQE_ERROR_ENBL 0x0080
> -#define TX_OK_ENBL 0x0100
> -#define TX_LATE_COL_ENBL 0x0200
> -#define TX_JBR_ENBL 0x0400
> -#define TX_ANY_COL_ENBL 0x0800
> -#define TX_16_COL_ENBL 0x8000
> -
> -/* PP_TxCMD - Transmit Command bit definition - Read-only */
> -#define TX_START_4_BYTES 0x0000
> -#define TX_START_64_BYTES 0x0040
> -#define TX_START_128_BYTES 0x0080
> -#define TX_START_ALL_BYTES 0x00C0
> -#define TX_FORCE 0x0100
> -#define TX_ONE_COL 0x0200
> -#define TX_TWO_PART_DEFF_DISABLE 0x0400
> -#define TX_NO_CRC 0x1000
> -#define TX_RUNT 0x2000
> -
> -/* PP_BufCFG - Buffer Configuration Interrupt Mask bit definition - Read/write */
> -#define GENERATE_SW_INTERRUPT 0x0040
> -#define RX_DMA_ENBL 0x0080
> -#define READY_FOR_TX_ENBL 0x0100
> -#define TX_UNDERRUN_ENBL 0x0200
> -#define RX_MISS_ENBL 0x0400
> -#define RX_128_BYTE_ENBL 0x0800
> -#define TX_COL_COUNT_OVRFLOW_ENBL 0x1000
> -#define RX_MISS_COUNT_OVRFLOW_ENBL 0x2000
> -#define RX_DEST_MATCH_ENBL 0x8000
> -
> -/* PP_LineCTL - Line Control bit definition - Read/write */
> -#define SERIAL_RX_ON 0x0040
> -#define SERIAL_TX_ON 0x0080
> -#define AUI_ONLY 0x0100
> -#define AUTO_AUI_10BASET 0x0200
> -#define MODIFIED_BACKOFF 0x0800
> -#define NO_AUTO_POLARITY 0x1000
> -#define TWO_PART_DEFDIS 0x2000
> -#define LOW_RX_SQUELCH 0x4000
> -
> -/* PP_SelfCTL - Software Self Control bit definition - Read/write */
> -#define POWER_ON_RESET 0x0040
> -#define SW_STOP 0x0100
> -#define SLEEP_ON 0x0200
> -#define AUTO_WAKEUP 0x0400
> -#define HCB0_ENBL 0x1000
> -#define HCB1_ENBL 0x2000
> -#define HCB0 0x4000
> -#define HCB1 0x8000
> -
> -/* PP_BusCTL - ISA Bus Control bit definition - Read/write */
> -#define RESET_RX_DMA 0x0040
> -#define MEMORY_ON 0x0400
> -#define DMA_BURST_MODE 0x0800
> -#define IO_CHANNEL_READY_ON 0x1000
> -#define RX_DMA_SIZE_64K 0x2000
> -#define ENABLE_IRQ 0x8000
> -
> -/* PP_TestCTL - Test Control bit definition - Read/write */
> -#define LINK_OFF 0x0080
> -#define ENDEC_LOOPBACK 0x0200
> -#define AUI_LOOPBACK 0x0400
> -#define BACKOFF_OFF 0x0800
> -#define FDX_8900 0x4000
> -#define FAST_TEST 0x8000
> -
> -/* PP_RxEvent - Receive Event Bit definition - Read-only */
> -#define RX_IA_HASHED 0x0040
> -#define RX_DRIBBLE 0x0080
> -#define RX_OK 0x0100
> -#define RX_HASHED 0x0200
> -#define RX_IA 0x0400
> -#define RX_BROADCAST 0x0800
> -#define RX_CRC_ERROR 0x1000
> -#define RX_RUNT 0x2000
> -#define RX_EXTRA_DATA 0x4000
> -
> -#define HASH_INDEX_MASK 0x0FC00
> -
> -/* PP_TxEvent - Transmit Event Bit definition - Read-only */
> -#define TX_LOST_CRS 0x0040
> -#define TX_SQE_ERROR 0x0080
> -#define TX_OK 0x0100
> -#define TX_LATE_COL 0x0200
> -#define TX_JBR 0x0400
> -#define TX_16_COL 0x8000
> -#define TX_SEND_OK_BITS (TX_OK|TX_LOST_CRS)
> -#define TX_COL_COUNT_MASK 0x7800
> -
> -/* PP_BufEvent - Buffer Event Bit definition - Read-only */
> -#define SW_INTERRUPT 0x0040
> -#define RX_DMA 0x0080
> -#define READY_FOR_TX 0x0100
> -#define TX_UNDERRUN 0x0200
> -#define RX_MISS 0x0400
> -#define RX_128_BYTE 0x0800
> -#define TX_COL_OVRFLW 0x1000
> -#define RX_MISS_OVRFLW 0x2000
> -#define RX_DEST_MATCH 0x8000
> -
> -/* PP_LineST - Ethernet Line Status bit definition - Read-only */
> -#define LINK_OK 0x0080
> -#define AUI_ON 0x0100
> -#define TENBASET_ON 0x0200
> -#define POLARITY_OK 0x1000
> -#define CRS_OK 0x4000
> -
> -/* PP_SelfST - Chip Software Status bit definition */
> -#define ACTIVE_33V 0x0040
> -#define INIT_DONE 0x0080
> -#define SI_BUSY 0x0100
> -#define EEPROM_PRESENT 0x0200
> -#define EEPROM_OK 0x0400
> -#define EL_PRESENT 0x0800
> -#define EE_SIZE_64 0x1000
> -
> -/* PP_BusST - ISA Bus Status bit definition */
> -#define TX_BID_ERROR 0x0080
> -#define READY_FOR_TX_NOW 0x0100
> -
> -/* PP_AutoNegCTL - Auto Negotiation Control bit definition */
> -#define RE_NEG_NOW 0x0040
> -#define ALLOW_FDX 0x0080
> -#define AUTO_NEG_ENABLE 0x0100
> -#define NLP_ENABLE 0x0200
> -#define FORCE_FDX 0x8000
> -#define AUTO_NEG_BITS (FORCE_FDX|NLP_ENABLE|AUTO_NEG_ENABLE)
> -#define AUTO_NEG_MASK (FORCE_FDX|NLP_ENABLE|AUTO_NEG_ENABLE|ALLOW_FDX|RE_NEG_NOW)
> -
> -/* PP_AutoNegST - Auto Negotiation Status bit definition */
> -#define AUTO_NEG_BUSY 0x0080
> -#define FLP_LINK 0x0100
> -#define FLP_LINK_GOOD 0x0800
> -#define LINK_FAULT 0x1000
> -#define HDX_ACTIVE 0x4000
> -#define FDX_ACTIVE 0x8000
> -
> -/*  The following block defines the ISQ event types */
> -#define ISQ_RECEIVER_EVENT 0x04
> -#define ISQ_TRANSMITTER_EVENT 0x08
> -#define ISQ_BUFFER_EVENT 0x0c
> -#define ISQ_RX_MISS_EVENT 0x10
> -#define ISQ_TX_COL_EVENT 0x12
> -
> -#define ISQ_EVENT_MASK 0x003F   /*  ISQ mask to find out type of event */
> -#define ISQ_HIST 16            /*  small history buffer */
> -#define AUTOINCREMENT 0x8000   /*  Bit mask to set bit-15 for autoincrement */
> -
> -#define TXRXBUFSIZE 0x0600
> -#define RXDMABUFSIZE 0x8000
> -#define RXDMASIZE 0x4000
> -#define TXRX_LENGTH_MASK 0x07FF
> -
> -/*  rx options bits */
> -#define RCV_WITH_RXON  1       /*  Set SerRx ON */
> -#define RCV_COUNTS     2       /*  Use Framecnt1 */
> -#define RCV_PONG       4       /*  Pong respondent */
> -#define RCV_DONG       8       /*  Dong operation */
> -#define RCV_POLLING    0x10    /*  Poll RxEvent */
> -#define RCV_ISQ                0x20    /*  Use ISQ, int */
> -#define RCV_AUTO_DMA   0x100   /*  Set AutoRxDMAE */
> -#define RCV_DMA                0x200   /*  Set RxDMA only */
> -#define RCV_DMA_ALL    0x400   /*  Copy all DMA'ed */
> -#define RCV_FIXED_DATA 0x800   /*  Every frame same */
> -#define RCV_IO         0x1000  /*  Use ISA IO only */
> -#define RCV_MEMORY     0x2000  /*  Use ISA Memory */
> -
> -#define RAM_SIZE       0x1000       /*  The card has 4k bytes or RAM */
> -#define PKT_START PP_TxFrame  /*  Start of packet RAM */
> -
> -#define RX_FRAME_PORT  0x0000
> -#define TX_FRAME_PORT RX_FRAME_PORT
> -#define TX_CMD_PORT    0x0004
> -#define TX_NOW         0x0000       /*  Tx packet after   5 bytes copied */
> -#define TX_AFTER_381   0x0040       /*  Tx packet after 381 bytes copied */
> -#define TX_AFTER_ALL   0x00c0       /*  Tx packet after all bytes copied */
> -#define TX_LEN_PORT    0x0006
> -#define ISQ_PORT       0x0008
> -#define ADD_PORT       0x000A
> -#define DATA_PORT      0x000C
> -
> -#define EEPROM_WRITE_EN                0x00F0
> -#define EEPROM_WRITE_DIS       0x0000
> -#define EEPROM_WRITE_CMD       0x0100
> -#define EEPROM_READ_CMD                0x0200
> -
> -/*  Receive Header */
> -/*  Description of header of each packet in receive area of memory */
> -#define RBUF_EVENT_LOW 0   /*  Low byte of RxEvent - status of received frame */
> -#define RBUF_EVENT_HIGH        1   /*  High byte of RxEvent - status of received frame */
> -#define RBUF_LEN_LOW   2   /*  Length of received data - low byte */
> -#define RBUF_LEN_HI    3   /*  Length of received data - high byte */
> -#define RBUF_HEAD_LEN  4   /*  Length of this header */
> -
> -#define CHIP_READ 0x1   /*  Used to mark state of the repins code (chip or dma) */
> -#define DMA_READ 0x2   /*  Used to mark state of the repins code (chip or dma) */
> -
> -/*  for bios scan */
> -/*  */
> -#ifdef CSDEBUG
> -/*  use these values for debugging bios scan */
> -#define BIOS_START_SEG 0x00000
> -#define BIOS_OFFSET_INC 0x0010
> -#else
> -#define BIOS_START_SEG 0x0c000
> -#define BIOS_OFFSET_INC 0x0200
> -#endif
> -
> -#define BIOS_LAST_OFFSET 0x0fc00
> -
> -/*  Byte offsets into the EEPROM configuration buffer */
> -#define ISA_CNF_OFFSET 0x6
> -#define TX_CTL_OFFSET (ISA_CNF_OFFSET + 8)                     /*  8900 eeprom */
> -#define AUTO_NEG_CNF_OFFSET (ISA_CNF_OFFSET + 8)               /*  8920 eeprom */
> -
> -  /*  the assumption here is that the bits in the eeprom are generally  */
> -  /*  in the same position as those in the autonegctl register. */
> -  /*  Of course the IMM bit is not in that register so it must be  */
> -  /*  masked out */
> -#define EE_FORCE_FDX  0x8000
> -#define EE_NLP_ENABLE 0x0200
> -#define EE_AUTO_NEG_ENABLE 0x0100
> -#define EE_ALLOW_FDX 0x0080
> -#define EE_AUTO_NEG_CNF_MASK (EE_FORCE_FDX|EE_NLP_ENABLE|EE_AUTO_NEG_ENABLE|EE_ALLOW_FDX)
> -
> -#define IMM_BIT 0x0040         /*  ignore missing media         */
> -
> -#define ADAPTER_CNF_OFFSET (AUTO_NEG_CNF_OFFSET + 2)
> -#define A_CNF_10B_T 0x0001
> -#define A_CNF_AUI 0x0002
> -#define A_CNF_10B_2 0x0004
> -#define A_CNF_MEDIA_TYPE 0x0070
> -#define A_CNF_MEDIA_AUTO 0x0070
> -#define A_CNF_MEDIA_10B_T 0x0020
> -#define A_CNF_MEDIA_AUI 0x0040
> -#define A_CNF_MEDIA_10B_2 0x0010
> -#define A_CNF_DC_DC_POLARITY 0x0080
> -#define A_CNF_NO_AUTO_POLARITY 0x2000
> -#define A_CNF_LOW_RX_SQUELCH 0x4000
> -#define A_CNF_EXTND_10B_2 0x8000
> -
> -#define PACKET_PAGE_OFFSET 0x8
> -
> -/*  Bit definitions for the ISA configuration word from the EEPROM */
> -#define INT_NO_MASK 0x000F
> -#define DMA_NO_MASK 0x0070
> -#define ISA_DMA_SIZE 0x0200
> -#define ISA_AUTO_RxDMA 0x0400
> -#define ISA_RxDMA 0x0800
> -#define DMA_BURST 0x1000
> -#define STREAM_TRANSFER 0x2000
> -#define ANY_ISA_DMA (ISA_AUTO_RxDMA | ISA_RxDMA)
> -
> -/*  DMA controller registers */
> -#define DMA_BASE 0x00     /*  DMA controller base */
> -#define DMA_BASE_2 0x0C0    /*  DMA controller base */
> -
> -#define DMA_STAT 0x0D0    /*  DMA controller status register */
> -#define DMA_MASK 0x0D4    /*  DMA controller mask register */
> -#define DMA_MODE 0x0D6    /*  DMA controller mode register */
> -#define DMA_RESETFF 0x0D8    /*  DMA controller first/last flip flop */
> -
> -/*  DMA data */
> -#define DMA_DISABLE 0x04     /*  Disable channel n */
> -#define DMA_ENABLE 0x00     /*  Enable channel n */
> -/*  Demand transfers, incr. address, auto init, writes, ch. n */
> -#define DMA_RX_MODE 0x14
> -/*  Demand transfers, incr. address, auto init, reads, ch. n */
> -#define DMA_TX_MODE 0x18
> -
> -#define DMA_SIZE (16*1024) /*  Size of dma buffer - 16k */
> -
> -#define CS8900 0x0000
> -#define CS8920 0x4000
> -#define CS8920M 0x6000
> -#define REVISON_BITS 0x1F00
> -#define EEVER_NUMBER 0x12
> -#define CHKSUM_LEN 0x14
> -#define CHKSUM_VAL 0x0000
> -#define START_EEPROM_DATA 0x001c /*  Offset into eeprom for start of data */
> -#define IRQ_MAP_EEPROM_DATA 0x0046 /*  Offset into eeprom for the IRQ map */
> -#define IRQ_MAP_LEN 0x0004 /*  No of bytes to read for the IRQ map */
> -#define PNP_IRQ_FRMT 0x0022 /*  PNP small item IRQ format */
> -#define CS8900_IRQ_MAP 0x1c20 /*  This IRQ map is fixed */
> -
> -#define CS8920_NO_INTS 0x0F   /*  Max CS8920 interrupt select # */
> -
> -#define PNP_ADD_PORT 0x0279
> -#define PNP_WRITE_PORT 0x0A79
> -
> -#define GET_PNP_ISA_STRUCT 0x40
> -#define PNP_ISA_STRUCT_LEN 0x06
> -#define PNP_CSN_CNT_OFF 0x01
> -#define PNP_RD_PORT_OFF 0x02
> -#define PNP_FUNCTION_OK 0x00
> -#define PNP_WAKE 0x03
> -#define PNP_RSRC_DATA 0x04
> -#define PNP_RSRC_READY 0x01
> -#define PNP_STATUS 0x05
> -#define PNP_ACTIVATE 0x30
> -#define PNP_CNF_IO_H 0x60
> -#define PNP_CNF_IO_L 0x61
> -#define PNP_CNF_INT 0x70
> -#define PNP_CNF_DMA 0x74
> -#define PNP_CNF_MEM 0x48
> diff --git a/drivers/net/ethernet/cirrus/mac89x0.c b/drivers/net/ethernet/cirrus/mac89x0.c
> deleted file mode 100644
> index 6723df9b65d9..000000000000
> --- a/drivers/net/ethernet/cirrus/mac89x0.c
> +++ /dev/null
> @@ -1,577 +0,0 @@
> -/* mac89x0.c: A Crystal Semiconductor CS89[02]0 driver for linux. */
> -/*
> -       Written 1996 by Russell Nelson, with reference to skeleton.c
> -       written 1993-1994 by Donald Becker.
> -
> -       This software may be used and distributed according to the terms
> -       of the GNU General Public License, incorporated herein by reference.
> -
> -       The author may be reached at nelson@crynwr.com, Crynwr
> -       Software, 11 Grant St., Potsdam, NY 13676
> -
> -  Changelog:
> -
> -  Mike Cruse        : mcruse@cti-ltd.com
> -                    : Changes for Linux 2.0 compatibility.
> -                    : Added dev_id parameter in net_interrupt(),
> -                    : request_irq() and free_irq(). Just NULL for now.
> -
> -  Mike Cruse        : Added MOD_INC_USE_COUNT and MOD_DEC_USE_COUNT macros
> -                    : in net_open() and net_close() so kerneld would know
> -                    : that the module is in use and wouldn't eject the
> -                    : driver prematurely.
> -
> -  Mike Cruse        : Rewrote init_module() and cleanup_module using 8390.c
> -                    : as an example. Disabled autoprobing in init_module(),
> -                    : not a good thing to do to other devices while Linux
> -                    : is running from all accounts.
> -
> -  Alan Cox          : Removed 1.2 support, added 2.1 extra counters.
> -
> -  David Huggins-Daines <dhd@debian.org>
> -
> -  Split this off into mac89x0.c, and gutted it of all parts which are
> -  not relevant to the existing CS8900 cards on the Macintosh
> -  (i.e. basically the Daynaport CS and LC cards).  To be precise:
> -
> -    * Removed all the media-detection stuff, because these cards are
> -    TP-only.
> -
> -    * Lobotomized the ISA interrupt bogosity, because these cards use
> -    a hardwired NuBus interrupt and a magic ISAIRQ value in the card.
> -
> -    * Basically eliminated everything not relevant to getting the
> -    cards minimally functioning on the Macintosh.
> -
> -  I might add that these cards are badly designed even from the Mac
> -  standpoint, in that Dayna, in their infinite wisdom, used NuBus slot
> -  I/O space and NuBus interrupts for these cards, but neglected to
> -  provide anything even remotely resembling a NuBus ROM.  Therefore we
> -  have to probe for them in a brain-damaged ISA-like fashion.
> -
> -  Arnaldo Carvalho de Melo <acme@conectiva.com.br> - 11/01/2001
> -  check kmalloc and release the allocated memory on failure in
> -  mac89x0_probe and in init_module
> -  use local_irq_{save,restore}(flags) in net_get_stat, not just
> -  local_irq_{dis,en}able()
> -*/
> -
> -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
> -
> -static const char version[] =
> -"cs89x0.c:v1.02 11/26/96 Russell Nelson <nelson@crynwr.com>\n";
> -
> -#include <linux/module.h>
> -
> -/*
> -  Sources:
> -
> -       Crynwr packet driver epktisa.
> -
> -       Crystal Semiconductor data sheets.
> -
> -*/
> -
> -#include <linux/kernel.h>
> -#include <linux/types.h>
> -#include <linux/fcntl.h>
> -#include <linux/interrupt.h>
> -#include <linux/ioport.h>
> -#include <linux/in.h>
> -#include <linux/string.h>
> -#include <linux/nubus.h>
> -#include <linux/errno.h>
> -#include <linux/init.h>
> -#include <linux/netdevice.h>
> -#include <linux/platform_device.h>
> -#include <linux/etherdevice.h>
> -#include <linux/skbuff.h>
> -#include <linux/delay.h>
> -#include <linux/bitops.h>
> -#include <linux/gfp.h>
> -
> -#include <asm/io.h>
> -#include <asm/hwtest.h>
> -#include <asm/macints.h>
> -
> -#include "cs89x0.h"
> -
> -static int debug = -1;
> -module_param(debug, int, 0);
> -MODULE_PARM_DESC(debug, "debug message level");
> -
> -/* Information that need to be kept for each board. */
> -struct net_local {
> -       int msg_enable;
> -       int chip_type;          /* one of: CS8900, CS8920, CS8920M */
> -       char chip_revision;     /* revision letter of the chip ('A'...) */
> -       int send_cmd;           /* the propercommand used to send a packet. */
> -       int rx_mode;
> -       int curr_rx_cfg;
> -        int send_underrun;      /* keep track of how many underruns in a row we get */
> -};
> -
> -/* Index to functions, as function prototypes. */
> -static int net_open(struct net_device *dev);
> -static netdev_tx_t net_send_packet(struct sk_buff *skb, struct net_device *dev);
> -static irqreturn_t net_interrupt(int irq, void *dev_id);
> -static void set_multicast_list(struct net_device *dev);
> -static void net_rx(struct net_device *dev);
> -static int net_close(struct net_device *dev);
> -static struct net_device_stats *net_get_stats(struct net_device *dev);
> -static int set_mac_address(struct net_device *dev, void *addr);
> -
> -/* For reading/writing registers ISA-style */
> -static inline int
> -readreg_io(struct net_device *dev, int portno)
> -{
> -       nubus_writew(swab16(portno), dev->base_addr + ADD_PORT);
> -       return swab16(nubus_readw(dev->base_addr + DATA_PORT));
> -}
> -
> -static inline void
> -writereg_io(struct net_device *dev, int portno, int value)
> -{
> -       nubus_writew(swab16(portno), dev->base_addr + ADD_PORT);
> -       nubus_writew(swab16(value), dev->base_addr + DATA_PORT);
> -}
> -
> -/* These are for reading/writing registers in shared memory */
> -static inline int
> -readreg(struct net_device *dev, int portno)
> -{
> -       return swab16(nubus_readw(dev->mem_start + portno));
> -}
> -
> -static inline void
> -writereg(struct net_device *dev, int portno, int value)
> -{
> -       nubus_writew(swab16(value), dev->mem_start + portno);
> -}
> -
> -static const struct net_device_ops mac89x0_netdev_ops = {
> -       .ndo_open               = net_open,
> -       .ndo_stop               = net_close,
> -       .ndo_start_xmit         = net_send_packet,
> -       .ndo_get_stats          = net_get_stats,
> -       .ndo_set_rx_mode        = set_multicast_list,
> -       .ndo_set_mac_address    = set_mac_address,
> -       .ndo_validate_addr      = eth_validate_addr,
> -};
> -
> -/* Probe for the CS8900 card in slot E.  We won't bother looking
> -   anywhere else until we have a really good reason to do so. */
> -static int mac89x0_device_probe(struct platform_device *pdev)
> -{
> -       struct net_device *dev;
> -       struct net_local *lp;
> -       int i, slot;
> -       unsigned rev_type = 0;
> -       unsigned long ioaddr;
> -       unsigned short sig;
> -       int err = -ENODEV;
> -       struct nubus_rsrc *fres;
> -
> -       dev = alloc_etherdev(sizeof(struct net_local));
> -       if (!dev)
> -               return -ENOMEM;
> -
> -       /* We might have to parameterize this later */
> -       slot = 0xE;
> -       /* Get out now if there's a real NuBus card in slot E */
> -       for_each_func_rsrc(fres)
> -               if (fres->board->slot == slot)
> -                       goto out;
> -
> -       /* The pseudo-ISA bits always live at offset 0x300 (gee,
> -           wonder why...) */
> -       ioaddr = (unsigned long)
> -               nubus_slot_addr(slot) | (((slot&0xf) << 20) + DEFAULTIOBASE);
> -       {
> -               int card_present;
> -
> -               card_present = (hwreg_present((void *)ioaddr + 4) &&
> -                               hwreg_present((void *)ioaddr + DATA_PORT));
> -               if (!card_present)
> -                       goto out;
> -       }
> -
> -       nubus_writew(0, ioaddr + ADD_PORT);
> -       sig = nubus_readw(ioaddr + DATA_PORT);
> -       if (sig != swab16(CHIP_EISA_ID_SIG))
> -               goto out;
> -
> -       SET_NETDEV_DEV(dev, &pdev->dev);
> -
> -       /* Initialize the net_device structure. */
> -       lp = netdev_priv(dev);
> -
> -       lp->msg_enable = netif_msg_init(debug, 0);
> -
> -       /* Fill in the 'dev' fields. */
> -       dev->base_addr = ioaddr;
> -       dev->mem_start = (unsigned long)
> -               nubus_slot_addr(slot) | (((slot&0xf) << 20) + MMIOBASE);
> -       dev->mem_end = dev->mem_start + 0x1000;
> -
> -       /* Turn on shared memory */
> -       writereg_io(dev, PP_BusCTL, MEMORY_ON);
> -
> -       /* get the chip type */
> -       rev_type = readreg(dev, PRODUCT_ID_ADD);
> -       lp->chip_type = rev_type &~ REVISON_BITS;
> -       lp->chip_revision = ((rev_type & REVISON_BITS) >> 8) + 'A';
> -
> -       /* Check the chip type and revision in order to set the correct send command
> -       CS8920 revision C and CS8900 revision F can use the faster send. */
> -       lp->send_cmd = TX_AFTER_381;
> -       if (lp->chip_type == CS8900 && lp->chip_revision >= 'F')
> -               lp->send_cmd = TX_NOW;
> -       if (lp->chip_type != CS8900 && lp->chip_revision >= 'C')
> -               lp->send_cmd = TX_NOW;
> -
> -       netif_dbg(lp, drv, dev, "%s", version);
> -
> -       pr_info("cs89%c0%s rev %c found at %#8lx\n",
> -               lp->chip_type == CS8900 ? '0' : '2',
> -               lp->chip_type == CS8920M ? "M" : "",
> -               lp->chip_revision, dev->base_addr);
> -
> -       /* Try to read the MAC address */
> -       if ((readreg(dev, PP_SelfST) & (EEPROM_PRESENT | EEPROM_OK)) == 0) {
> -               pr_info("No EEPROM, giving up now.\n");
> -               goto out1;
> -        } else {
> -               u8 addr[ETH_ALEN];
> -
> -                for (i = 0; i < ETH_ALEN; i += 2) {
> -                       /* Big-endian (why??!) */
> -                       unsigned short s = readreg(dev, PP_IA + i);
> -                       addr[i] = s >> 8;
> -                       addr[i+1] = s & 0xff;
> -                }
> -               eth_hw_addr_set(dev, addr);
> -        }
> -
> -       dev->irq = SLOT2IRQ(slot);
> -
> -       /* print the IRQ and ethernet address. */
> -
> -       pr_info("MAC %pM, IRQ %d\n", dev->dev_addr, dev->irq);
> -
> -       dev->netdev_ops         = &mac89x0_netdev_ops;
> -
> -       err = register_netdev(dev);
> -       if (err)
> -               goto out1;
> -
> -       platform_set_drvdata(pdev, dev);
> -       return 0;
> -out1:
> -       nubus_writew(0, dev->base_addr + ADD_PORT);
> -out:
> -       free_netdev(dev);
> -       return err;
> -}
> -
> -/* Open/initialize the board.  This is called (in the current kernel)
> -   sometime after booting when the 'ifconfig' program is run.
> -
> -   This routine should set everything up anew at each open, even
> -   registers that "should" only need to be set once at boot, so that
> -   there is non-reboot way to recover if something goes wrong.
> -   */
> -static int
> -net_open(struct net_device *dev)
> -{
> -       struct net_local *lp = netdev_priv(dev);
> -       int i;
> -
> -       /* Disable the interrupt for now */
> -       writereg(dev, PP_BusCTL, readreg(dev, PP_BusCTL) & ~ENABLE_IRQ);
> -
> -       /* Grab the interrupt */
> -       if (request_irq(dev->irq, net_interrupt, 0, "cs89x0", dev))
> -               return -EAGAIN;
> -
> -       /* Set up the IRQ - Apparently magic */
> -       if (lp->chip_type == CS8900)
> -               writereg(dev, PP_CS8900_ISAINT, 0);
> -       else
> -               writereg(dev, PP_CS8920_ISAINT, 0);
> -
> -       /* set the Ethernet address */
> -       for (i=0; i < ETH_ALEN/2; i++)
> -               writereg(dev, PP_IA+i*2, dev->dev_addr[i*2] | (dev->dev_addr[i*2+1] << 8));
> -
> -       /* Turn on both receive and transmit operations */
> -       writereg(dev, PP_LineCTL, readreg(dev, PP_LineCTL) | SERIAL_RX_ON | SERIAL_TX_ON);
> -
> -       /* Receive only error free packets addressed to this card */
> -       lp->rx_mode = 0;
> -       writereg(dev, PP_RxCTL, DEF_RX_ACCEPT);
> -
> -       lp->curr_rx_cfg = RX_OK_ENBL | RX_CRC_ERROR_ENBL;
> -
> -       writereg(dev, PP_RxCFG, lp->curr_rx_cfg);
> -
> -       writereg(dev, PP_TxCFG, TX_LOST_CRS_ENBL | TX_SQE_ERROR_ENBL | TX_OK_ENBL |
> -              TX_LATE_COL_ENBL | TX_JBR_ENBL | TX_ANY_COL_ENBL | TX_16_COL_ENBL);
> -
> -       writereg(dev, PP_BufCFG, READY_FOR_TX_ENBL | RX_MISS_COUNT_OVRFLOW_ENBL |
> -                TX_COL_COUNT_OVRFLOW_ENBL | TX_UNDERRUN_ENBL);
> -
> -       /* now that we've got our act together, enable everything */
> -       writereg(dev, PP_BusCTL, readreg(dev, PP_BusCTL) | ENABLE_IRQ);
> -       netif_start_queue(dev);
> -       return 0;
> -}
> -
> -static netdev_tx_t
> -net_send_packet(struct sk_buff *skb, struct net_device *dev)
> -{
> -       struct net_local *lp = netdev_priv(dev);
> -       unsigned long flags;
> -
> -       netif_dbg(lp, tx_queued, dev, "sent %d byte packet of type %x\n",
> -                 skb->len, skb->data[ETH_ALEN + ETH_ALEN] << 8 |
> -                 skb->data[ETH_ALEN + ETH_ALEN + 1]);
> -
> -       /* keep the upload from being interrupted, since we
> -          ask the chip to start transmitting before the
> -          whole packet has been completely uploaded. */
> -       local_irq_save(flags);
> -       netif_stop_queue(dev);
> -
> -       /* initiate a transmit sequence */
> -       writereg(dev, PP_TxCMD, lp->send_cmd);
> -       writereg(dev, PP_TxLength, skb->len);
> -
> -       /* Test to see if the chip has allocated memory for the packet */
> -       if ((readreg(dev, PP_BusST) & READY_FOR_TX_NOW) == 0) {
> -               /* Gasp!  It hasn't.  But that shouldn't happen since
> -                  we're waiting for TxOk, so return 1 and requeue this packet. */
> -               local_irq_restore(flags);
> -               return NETDEV_TX_BUSY;
> -       }
> -
> -       /* Write the contents of the packet */
> -       skb_copy_from_linear_data(skb, (void *)(dev->mem_start + PP_TxFrame),
> -                                 skb->len+1);
> -
> -       local_irq_restore(flags);
> -       dev_kfree_skb (skb);
> -
> -       return NETDEV_TX_OK;
> -}
> -
> -/* The typical workload of the driver:
> -   Handle the network interface interrupts. */
> -static irqreturn_t net_interrupt(int irq, void *dev_id)
> -{
> -       struct net_device *dev = dev_id;
> -       struct net_local *lp;
> -       int ioaddr, status;
> -
> -       ioaddr = dev->base_addr;
> -       lp = netdev_priv(dev);
> -
> -       /* we MUST read all the events out of the ISQ, otherwise we'll never
> -           get interrupted again.  As a consequence, we can't have any limit
> -           on the number of times we loop in the interrupt handler.  The
> -           hardware guarantees that eventually we'll run out of events.  Of
> -           course, if you're on a slow machine, and packets are arriving
> -           faster than you can read them off, you're screwed.  Hasta la
> -           vista, baby!  */
> -       while ((status = swab16(nubus_readw(dev->base_addr + ISQ_PORT)))) {
> -               netif_dbg(lp, intr, dev, "status=%04x\n", status);
> -               switch(status & ISQ_EVENT_MASK) {
> -               case ISQ_RECEIVER_EVENT:
> -                       /* Got a packet(s). */
> -                       net_rx(dev);
> -                       break;
> -               case ISQ_TRANSMITTER_EVENT:
> -                       dev->stats.tx_packets++;
> -                       netif_wake_queue(dev);
> -                       if ((status & TX_OK) == 0)
> -                               dev->stats.tx_errors++;
> -                       if (status & TX_LOST_CRS)
> -                               dev->stats.tx_carrier_errors++;
> -                       if (status & TX_SQE_ERROR)
> -                               dev->stats.tx_heartbeat_errors++;
> -                       if (status & TX_LATE_COL)
> -                               dev->stats.tx_window_errors++;
> -                       if (status & TX_16_COL)
> -                               dev->stats.tx_aborted_errors++;
> -                       break;
> -               case ISQ_BUFFER_EVENT:
> -                       if (status & READY_FOR_TX) {
> -                               /* we tried to transmit a packet earlier,
> -                                   but inexplicably ran out of buffers.
> -                                   That shouldn't happen since we only ever
> -                                   load one packet.  Shrug.  Do the right
> -                                   thing anyway. */
> -                               netif_wake_queue(dev);
> -                       }
> -                       if (status & TX_UNDERRUN) {
> -                               netif_dbg(lp, tx_err, dev, "transmit underrun\n");
> -                                lp->send_underrun++;
> -                                if (lp->send_underrun == 3) lp->send_cmd = TX_AFTER_381;
> -                                else if (lp->send_underrun == 6) lp->send_cmd = TX_AFTER_ALL;
> -                        }
> -                       break;
> -               case ISQ_RX_MISS_EVENT:
> -                       dev->stats.rx_missed_errors += (status >> 6);
> -                       break;
> -               case ISQ_TX_COL_EVENT:
> -                       dev->stats.collisions += (status >> 6);
> -                       break;
> -               }
> -       }
> -       return IRQ_HANDLED;
> -}
> -
> -/* We have a good packet(s), get it/them out of the buffers. */
> -static void
> -net_rx(struct net_device *dev)
> -{
> -       struct net_local *lp = netdev_priv(dev);
> -       struct sk_buff *skb;
> -       int status, length;
> -
> -       status = readreg(dev, PP_RxStatus);
> -       if ((status & RX_OK) == 0) {
> -               dev->stats.rx_errors++;
> -               if (status & RX_RUNT)
> -                               dev->stats.rx_length_errors++;
> -               if (status & RX_EXTRA_DATA)
> -                               dev->stats.rx_length_errors++;
> -               if ((status & RX_CRC_ERROR) &&
> -                   !(status & (RX_EXTRA_DATA|RX_RUNT)))
> -                       /* per str 172 */
> -                       dev->stats.rx_crc_errors++;
> -               if (status & RX_DRIBBLE)
> -                               dev->stats.rx_frame_errors++;
> -               return;
> -       }
> -
> -       length = readreg(dev, PP_RxLength);
> -       /* Malloc up new buffer. */
> -       skb = alloc_skb(length, GFP_ATOMIC);
> -       if (skb == NULL) {
> -               dev->stats.rx_dropped++;
> -               return;
> -       }
> -       skb_put(skb, length);
> -
> -       skb_copy_to_linear_data(skb, (void *)(dev->mem_start + PP_RxFrame),
> -                               length);
> -
> -       netif_dbg(lp, rx_status, dev, "received %d byte packet of type %x\n",
> -                 length, skb->data[ETH_ALEN + ETH_ALEN] << 8 |
> -                 skb->data[ETH_ALEN + ETH_ALEN + 1]);
> -
> -        skb->protocol=eth_type_trans(skb,dev);
> -       netif_rx(skb);
> -       dev->stats.rx_packets++;
> -       dev->stats.rx_bytes += length;
> -}
> -
> -/* The inverse routine to net_open(). */
> -static int
> -net_close(struct net_device *dev)
> -{
> -
> -       writereg(dev, PP_RxCFG, 0);
> -       writereg(dev, PP_TxCFG, 0);
> -       writereg(dev, PP_BufCFG, 0);
> -       writereg(dev, PP_BusCTL, 0);
> -
> -       netif_stop_queue(dev);
> -
> -       free_irq(dev->irq, dev);
> -
> -       /* Update the statistics here. */
> -
> -       return 0;
> -
> -}
> -
> -/* Get the current statistics. This may be called with the card open or
> -   closed. */
> -static struct net_device_stats *
> -net_get_stats(struct net_device *dev)
> -{
> -       unsigned long flags;
> -
> -       local_irq_save(flags);
> -       /* Update the statistics from the device registers. */
> -       dev->stats.rx_missed_errors += (readreg(dev, PP_RxMiss) >> 6);
> -       dev->stats.collisions += (readreg(dev, PP_TxCol) >> 6);
> -       local_irq_restore(flags);
> -
> -       return &dev->stats;
> -}
> -
> -static void set_multicast_list(struct net_device *dev)
> -{
> -       struct net_local *lp = netdev_priv(dev);
> -
> -       if(dev->flags&IFF_PROMISC)
> -       {
> -               lp->rx_mode = RX_ALL_ACCEPT;
> -       } else if ((dev->flags & IFF_ALLMULTI) || !netdev_mc_empty(dev)) {
> -               /* The multicast-accept list is initialized to accept-all, and we
> -                  rely on higher-level filtering for now. */
> -               lp->rx_mode = RX_MULTCAST_ACCEPT;
> -       }
> -       else
> -               lp->rx_mode = 0;
> -
> -       writereg(dev, PP_RxCTL, DEF_RX_ACCEPT | lp->rx_mode);
> -
> -       /* in promiscuous mode, we accept errored packets, so we have to enable interrupts on them also */
> -       writereg(dev, PP_RxCFG, lp->curr_rx_cfg |
> -            (lp->rx_mode == RX_ALL_ACCEPT? (RX_CRC_ERROR_ENBL|RX_RUNT_ENBL|RX_EXTRA_DATA_ENBL) : 0));
> -}
> -
> -
> -static int set_mac_address(struct net_device *dev, void *addr)
> -{
> -       struct sockaddr *saddr = addr;
> -       int i;
> -
> -       if (!is_valid_ether_addr(saddr->sa_data))
> -               return -EADDRNOTAVAIL;
> -
> -       eth_hw_addr_set(dev, saddr->sa_data);
> -       netdev_info(dev, "Setting MAC address to %pM\n", dev->dev_addr);
> -
> -       /* set the Ethernet address */
> -       for (i=0; i < ETH_ALEN/2; i++)
> -               writereg(dev, PP_IA+i*2, dev->dev_addr[i*2] | (dev->dev_addr[i*2+1] << 8));
> -
> -       return 0;
> -}
> -
> -MODULE_DESCRIPTION("Macintosh CS89x0-based Ethernet driver");
> -MODULE_LICENSE("GPL");
> -
> -static void mac89x0_device_remove(struct platform_device *pdev)
> -{
> -       struct net_device *dev = platform_get_drvdata(pdev);
> -
> -       unregister_netdev(dev);
> -       nubus_writew(0, dev->base_addr + ADD_PORT);
> -       free_netdev(dev);
> -}
> -
> -static struct platform_driver mac89x0_platform_driver = {
> -       .probe = mac89x0_device_probe,
> -       .remove = mac89x0_device_remove,
> -       .driver = {
> -               .name = "mac89x0",
> -       },
> -};
> -
> -module_platform_driver(mac89x0_platform_driver);

^ permalink raw reply

* Re: [PATCH net 11/18] drivers: net: cirrus: cs89x0: Remove this driver
From: Geert Uytterhoeven @ 2026-04-22  7:31 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Simon Horman, Jonathan Corbet, Shuah Khan,
	linux-kernel, netdev, linux-doc
In-Reply-To: <20260421-v7-0-0-net-next-driver-removal-v1-v1-11-69517c689d1f@lunn.ch>

Hi Andrew,

On Wed, 22 Apr 2026 at 03:04, Andrew Lunn <andrew@lunn.ch> wrote:
> The cs89x0 was written by Bonald Becker 1993 to 1994. It is an ISA
> device, so unlikely to be used with modern kernels.
>
> Signed-off-by: Andrew Lunn <andrew@lunn.ch>

Thanks for your patch!

> --- a/drivers/net/ethernet/cirrus/Kconfig
> +++ b/drivers/net/ethernet/cirrus/Kconfig
> @@ -17,36 +17,6 @@ config NET_VENDOR_CIRRUS
>
>  if NET_VENDOR_CIRRUS
>
> -config CS89x0
> -       tristate
> -
> -config CS89x0_ISA
> -       tristate "CS89x0 ISA driver support"
> -       depends on HAS_IOPORT_MAP
> -       depends on ISA
> -       depends on !PPC32
> -       depends on CS89x0_PLATFORM=n
> -       select NETDEV_LEGACY_INIT
> -       select CS89x0
> -       help
> -         Support for CS89x0 chipset based Ethernet cards. If you have a
> -         network (Ethernet) card of this type, say Y and read the file
> -         <file:Documentation/networking/device_drivers/ethernet/cirrus/cs89x0.rst>.
> -
> -         To compile this driver as a module, choose M here. The module
> -         will be called cs89x0.

This is the driver for the old twentieth-century ISA device...

> -
> -config CS89x0_PLATFORM
> -       tristate "CS89x0 platform driver support"
> -       depends on ARM || (COMPILE_TEST && !PPC)
> -       select CS89x0
> -       help
> -         Say Y to compile the cs89x0 platform driver. This makes this driver
> -         suitable for use on certain evaluation boards such as the iMX21ADS.
> -
> -         To compile this driver as a module, choose M here. The module
> -         will be called cs89x0.

This is the more modern DT-based part...

> --- a/drivers/net/ethernet/cirrus/cs89x0.c
> +++ /dev/null

> -#if IS_ENABLED(CONFIG_CS89x0_PLATFORM)

[...]

> -static const struct of_device_id __maybe_unused cs89x0_match[] = {
> -       { .compatible = "cirrus,cs8900", },
> -       { .compatible = "cirrus,cs8920", },
> -       { },
> -};
> -MODULE_DEVICE_TABLE(of, cs89x0_match);

[...]

> -#endif /* CONFIG_CS89x0_PLATFORM */

However, no users of these compatible values ever appeared upstream.

Gr{oetje,eeting}s,

                        Geert


--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply

* Re: [PATCH net v8 03/15] net: cache snapshot entries for ndo_set_rx_mode_async
From: Paolo Abeni @ 2026-04-22  7:27 UTC (permalink / raw)
  To: Stanislav Fomichev; +Cc: netdev, davem, edumazet, kuba
In-Reply-To: <aef3wzOywP8_LhCh@devvm17672.vll0.facebook.com>

On 4/22/26 12:19 AM, Stanislav Fomichev wrote:
> On 04/21, Paolo Abeni wrote:
>> On 4/21/26 11:52 AM, Paolo Abeni wrote:
>>> On 4/16/26 8:57 PM, Stanislav Fomichev wrote:
>>>> Add a per-device netdev_hw_addr_list cache (rx_mode_addr_cache) that
>>>> allows __hw_addr_list_snapshot() and __hw_addr_list_reconcile() to
>>>> reuse previously allocated entries instead of hitting GFP_ATOMIC on
>>>> every snapshot cycle.
>>>>
>>>> snapshot pops entries from the cache when available, falling back to
>>>> __hw_addr_create(). reconcile splices both snapshot lists back into
>>>> the cache via __hw_addr_splice(). The cache is flushed in
>>>> free_netdev().
>>>>
>>>> Signed-off-by: Stanislav Fomichev <sdf@fomichev.me>
>>>> (cherry picked from commit ba3ab1832a511f660fdc6231245b14bf610c05bd)
>>>
>>> Are you backporting from 7.2 via time machine??? :-P
>>>
>>>> @@ -611,8 +633,8 @@ void __hw_addr_list_reconcile(struct netdev_hw_addr_list *real_list,
>>>>  		}
>>>>  	}
>>>>  
>>>> -	__hw_addr_flush(work);
>>>> -	__hw_addr_flush(ref);
>>>> +	__hw_addr_splice(cache, work);
>>>> +	__hw_addr_splice(cache, ref);
>>>
>>> I think here sashiko has a point, with the cache size being unbounded. I
>>> guess syzkaller or the like will find a way to make it grow too much.
>>>
>>> What about hard-limit it to some reasonable value?!?
>>
>> There are a few more remarks from sashiko at the driver level, but
>> AFAICS are all pre-existing issues.
>>
>> I think even the above one it's better handled as a follow-up, so I'm
>> applying the series as-is (I'll just drop the cherry-pick statement above).
> 
> I have a follow-up series to add retries here, but not sure it's the
> right direction. I can send it once net-next opens just to opinions.

I'm not sure how you are going to use retries with cache access?!?
Likely some code could clarify.

I was wondering about a dumb limit for such cache, possibly netns-wide,
possibly with a paired sysctl.

/P


^ permalink raw reply

* [PATCH net] net: txgbe: fix firmware version check
From: Jiawen Wu @ 2026-04-22  7:18 UTC (permalink / raw)
  To: netdev
  Cc: Mengyuan Lou, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Simon Horman, Jacob Keller,
	Jiawen Wu, stable

For the device SP, the firmware version is a 32-bit value where the
lower 20 bits represent the base version number. And the customized
firmware version populates the upper 12 bits with a specific
identification number.

For other devices AML 25G and 40G, the upper 12 bits of the firmware
version is always non-zero, and they have other naming conventions.

Only SP devices need to check this to tell if XPCS will work properly.
So the judgement of MAC type is added here.

And the original logic compared the entire 32-bit value against 0x20010,
which caused the outdated base firmwares bypass the version check
without a warning. Apply a mask 0xfffff to isolate the lower 20 bits for
an accurate base version comparison.

Fixes: ab928c24e6cd ("net: txgbe: add FW version warning")
Cc: stable@vger.kernel.org
Signed-off-by: Jiawen Wu <jiawenwu@trustnetic.com>
---
 drivers/net/ethernet/wangxun/txgbe/txgbe_main.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
index ec32a5f422f2..8b7c3753bb6a 100644
--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
+++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
@@ -864,7 +864,8 @@ static int txgbe_probe(struct pci_dev *pdev,
 			 "0x%08x", etrack_id);
 	}
 
-	if (etrack_id < 0x20010)
+	if (wx->mac.type == wx_mac_sp &&
+	    ((etrack_id & 0xfffff) < 0x20010))
 		dev_warn(&pdev->dev, "Please upgrade the firmware to 0x20010 or above.\n");
 
 	err = txgbe_test_hostif(wx);
-- 
2.51.0


^ permalink raw reply related

* Re: [PATCH net v4 2/2] selftests/bpf: check epoll readiness during reuseport migration
From: Zhenzhong Wu @ 2026-04-22  7:14 UTC (permalink / raw)
  To: Kuniyuki Iwashima
  Cc: Tamir Duberstein, netdev, edumazet, ncardwell, davem, dsahern,
	kuba, pabeni, horms, shuah, linux-kernel, linux-kselftest
In-Reply-To: <CAAVpQUAKCDVPHhFjWch2-zpKp2rHEPzvwE4R1UrDTMd_6Y2HYA@mail.gmail.com>

Thanks both. Keeping the goto for consistency with the rest of the test.

On Wed, Apr 22, 2026 at 2:40 PM Kuniyuki Iwashima <kuniyu@google.com> wrote:
>
> On Tue, Apr 21, 2026 at 11:34 PM Zhenzhong Wu <jt26wzz@gmail.com> wrote:
> >
> > Thanks Tamir, I will fold this into v5 - there's already a precedent
> > in socket_helpers.h, so I will just include it from there.
>
> The test does not use cleanup in other places,
> no need to mix them up.
>
>
> >
> > On Wed, Apr 22, 2026 at 11:04 AM Tamir Duberstein <tamird@kernel.org> wrote:
> > >
> > > On Tue, Apr 21, 2026 at 7:46 PM Zhenzhong Wu <jt26wzz@gmail.com> wrote:
> > > >
> > > > Inside migrate_dance(), add epoll checks around shutdown() to
> > > > verify that the target listener is not ready before shutdown()
> > > > and becomes ready immediately after shutdown() triggers migration.
> > > >
> > > > Cover TCP_ESTABLISHED and TCP_SYN_RECV. Exclude TCP_NEW_SYN_RECV
> > > > as it depends on later handshake completion.
> > > >
> > > > Suggested-by: Kuniyuki Iwashima <kuniyu@google.com>
> > > > Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
> > > > Signed-off-by: Zhenzhong Wu <jt26wzz@gmail.com>
> > > > ---
> > > >  .../bpf/prog_tests/migrate_reuseport.c        | 49 ++++++++++++++++---
> > > >  1 file changed, 42 insertions(+), 7 deletions(-)
> > > >
> > > > diff --git a/tools/testing/selftests/bpf/prog_tests/migrate_reuseport.c b/tools/testing/selftests/bpf/prog_tests/migrate_reuseport.c
> > > > index 653b0a20f..c62907732 100644
> > > > --- a/tools/testing/selftests/bpf/prog_tests/migrate_reuseport.c
> > > > +++ b/tools/testing/selftests/bpf/prog_tests/migrate_reuseport.c
> > > > @@ -7,24 +7,29 @@
> > > >   *   3. call listen() for 1 server socket. (migration target)
> > > >   *   4. update a map to migrate all child sockets
> > > >   *        to the last server socket (migrate_map[cookie] = 4)
> > > > - *   5. call shutdown() for first 4 server sockets
> > > > + *   5. for TCP_ESTABLISHED and TCP_SYN_RECV cases, verify via epoll
> > > > + *        that the last server socket is not ready before migration.
> > > > + *   6. call shutdown() for first 4 server sockets
> > > >   *        and migrate the requests in the accept queue
> > > >   *        to the last server socket.
> > > > - *   6. call listen() for the second server socket.
> > > > - *   7. call shutdown() for the last server
> > > > + *   7. for TCP_ESTABLISHED and TCP_SYN_RECV cases, verify via epoll
> > > > + *        that the last server socket is ready after migration.
> > > > + *   8. call listen() for the second server socket.
> > > > + *   9. call shutdown() for the last server
> > > >   *        and migrate the requests in the accept queue
> > > >   *        to the second server socket.
> > > > - *   8. call listen() for the last server.
> > > > - *   9. call shutdown() for the second server
> > > > + *  10. call listen() for the last server.
> > > > + *  11. call shutdown() for the second server
> > > >   *        and migrate the requests in the accept queue
> > > >   *        to the last server socket.
> > > > - *  10. call accept() for the last server socket.
> > > > + *  12. call accept() for the last server socket.
> > > >   *
> > > >   * Author: Kuniyuki Iwashima <kuniyu@amazon.co.jp>
> > > >   */
> > > >
> > > >  #include <bpf/bpf.h>
> > > >  #include <bpf/libbpf.h>
> > > > +#include <sys/epoll.h>
> > > >
> > > >  #include "test_progs.h"
> > > >  #include "test_migrate_reuseport.skel.h"
> > > > @@ -350,21 +355,51 @@ static int update_maps(struct migrate_reuseport_test_case *test_case,
> > > >
> > > >  static int migrate_dance(struct migrate_reuseport_test_case *test_case)
> > > >  {
> > > > +       struct epoll_event ev = {
> > > > +               .events = EPOLLIN,
> > > > +       };
> > > > +       int epoll = -1, nfds;
> > > >         int i, err;
> > > >
> > > > +       if (test_case->state != BPF_TCP_NEW_SYN_RECV) {
> > > > +               epoll = epoll_create1(0);
> > > > +               if (!ASSERT_NEQ(epoll, -1, "epoll_create1"))
> > > > +                       return -1;
> > > > +
> > > > +               ev.data.fd = test_case->servers[MIGRATED_TO];
> > > > +               if (!ASSERT_OK(epoll_ctl(epoll, EPOLL_CTL_ADD,
> > > > +                                        test_case->servers[MIGRATED_TO], &ev),
> > > > +                              "epoll_ctl"))
> > > > +                       goto close_epoll;
> > > > +
> > > > +               nfds = epoll_wait(epoll, &ev, 1, 0);
> > > > +               if (!ASSERT_EQ(nfds, 0, "epoll_wait 1"))
> > > > +                       goto close_epoll;
> > > > +       }
> > > > +
> > > >         /* Migrate TCP_ESTABLISHED and TCP_SYN_RECV requests
> > > >          * to the last listener based on eBPF.
> > > >          */
> > > >         for (i = 0; i < MIGRATED_TO; i++) {
> > > >                 err = shutdown(test_case->servers[i], SHUT_RDWR);
> > > >                 if (!ASSERT_OK(err, "shutdown"))
> > > > -                       return -1;
> > > > +                       goto close_epoll;
> > > >         }
> > > >
> > > >         /* No dance for TCP_NEW_SYN_RECV to migrate based on eBPF */
> > > >         if (test_case->state == BPF_TCP_NEW_SYN_RECV)
> > > >                 return 0;
> > > >
> > > > +       nfds = epoll_wait(epoll, &ev, 1, 0);
> > > > +       if (!ASSERT_EQ(nfds, 1, "epoll_wait 2")) {
> > > > +close_epoll:
> > > > +               if (epoll >= 0)
> > > > +                       close(epoll);
> > > > +               return -1;
> > > > +       }
> > >
> > > I think you can avoid this goto using `__attribute__((cleanup(...))`:
> > >
> > >   static void close_fd(int *fd)
> > >   {
> > >         if (*fd >= 0)
> > >                 close(*fd);
> > >   }
> > >
> > >   #define __close_fd __attribute__((cleanup(close_fd)))
> > >
> > > then in the test:
> > >
> > > __close_fd int epoll = -1;
> > >
> > > there's an example of this in
> > > tools/testing/selftests/bpf/prog_tests/socket_helpers.h.

^ permalink raw reply

* Re: [PATCH net-deletions v2] net: remove unused ATM protocols and legacy ATM device drivers
From: Andy Shevchenko @ 2026-04-22  7:08 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: davem, netdev, edumazet, pabeni, andrew+netdev, horms, corbet,
	skhan, linux, tsbogend, maddy, mpe, npiggin, chleroy, 3chas3,
	razor, idosch, jani.nikula, mchehab+huawei, tytso, herbert, geert,
	ebiggers, johannes.berg, jonathan.cameron, kees, kuniyu,
	fourier.thomas, rdunlap, akpm, linux-doc, linux-mips,
	linuxppc-dev, bridge, dwmw2
In-Reply-To: <20260422041846.2035118-1-kuba@kernel.org>

On Tue, Apr 21, 2026 at 09:18:44PM -0700, Jakub Kicinski wrote:
> Remove the ATM protocol modules and PCI/SBUS ATM device drivers
> that are no longer in active use.
> 
> The ATM core protocol stack, PPPoATM, BR2684, and USB DSL modem
> drivers (drivers/usb/atm/) are retained in-tree to maintain PPP
> over ATM (PPPoA) and PPPoE-over-BR2684 support for DSL connections.
> 
> Removed ATM protocol modules:
>  - net/atm/clip.c - Classical IP over ATM (RFC 2225)
>  - net/atm/lec.c - LAN Emulation Client (LANE)
>  - net/atm/mpc.c, mpoa_caches.c, mpoa_proc.c - Multi-Protocol Over ATM
> 
> Removed PCI/SBUS ATM device drivers (drivers/atm/):
>  - adummy, atmtcp - software/testing ATM devices
>  - eni - Efficient Networks ENI155P (OC-3, ~1995)
>  - fore200e - FORE Systems 200E PCI/SBUS (OC-3, ~1999)
>  - he - ForeRunner HE (OC-3/OC-12, ~2000)
>  - idt77105 - IDT 77105 25 Mbps ATM PHY
>  - idt77252 - IDT 77252 NICStAR II (OC-3, ~2000)
>  - iphase - Interphase ATM PCI (OC-3/DS3/E3)
>  - lanai - Efficient Networks Speedstream 3010
>  - nicstar - IDT 77201 NICStAR (155/25 Mbps, ~1999)
>  - solos-pci - Traverse Technologies ADSL2+ PCI
>  - suni - PMC S/UNI SONET PHY library
> 
> Also clean up references in:
>  - net/bridge/ - remove ATM LANE hook (br_fdb_test_addr_hook,
>    br_fdb_test_addr)
>  - net/core/dev.c - remove br_fdb_test_addr_hook export
>  - defconfig files - remove ATM driver config options
> 
> The removed code is moved to an out-of-tree module package (mod-orphan).
> 
> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
> ---
> v2:
>  - keep BR2684
>  - correct the claim that Traverse Technologies is defunct,
>    I'm still deleting the solos driver, chances are nobody uses it.
>    Easy enough to revert back in since core is still around.
>    The guiding principle is to keep USB modems and delete
>    the rest as USB ADSL2+ CPEs were most popular historically.
> v1: https://lore.kernel.org/20260421021943.1295109-1-kuba@kernel.org
> 
> CC: corbet@lwn.net
> CC: skhan@linuxfoundation.org
> CC: linux@armlinux.org.uk
> CC: tsbogend@alpha.franken.de
> CC: maddy@linux.ibm.com
> CC: mpe@ellerman.id.au
> CC: npiggin@gmail.com
> CC: chleroy@kernel.org
> CC: 3chas3@gmail.com
> CC: razor@blackwall.org
> CC: idosch@nvidia.com
> CC: jani.nikula@intel.com
> CC: mchehab+huawei@kernel.org
> CC: tytso@mit.edu
> CC: herbert@gondor.apana.org.au
> CC: geert@linux-m68k.org
> CC: ebiggers@kernel.org
> CC: johannes.berg@intel.com
> CC: jonathan.cameron@huawei.com
> CC: kees@kernel.org
> CC: kuniyu@google.com
> CC: fourier.thomas@gmail.com
> CC: andriy.shevchenko@intel.com
> CC: rdunlap@infradead.org
> CC: akpm@linux-foundation.org
> CC: linux-doc@vger.kernel.org
> CC: linux-mips@vger.kernel.org
> CC: linuxppc-dev@lists.ozlabs.org
> CC: bridge@lists.linux.dev
> CC: dwmw2@infradead.org
> CC: herbert@gondor.apana.org.au

Acked-by: Andy Shevchenko <andriy.shevchenko@intel.com>

P.S.
Since it's almost removal and it will go via netdev tree (same tree you are
maintaining, I suppose) the -D would have a big help to review the changes
(and not see removals at all, as 32k lines of one email is too much).

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply

* Re: [net-next PATCH 08/10] net: dsa: realtek: rtl8365mb: add FDB support
From: Luiz Angelo Daros de Luca @ 2026-04-22  6:56 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Andrew Lunn, Vladimir Oltean, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Simon Horman, Alvin Šipraga,
	Yury Norov, Rasmus Villemoes, Russell King, netdev, linux-kernel
In-Reply-To: <CAD++jLnbZ6q+Noe9abWWRNrvYVjCU-X3w4jpzKKYQDUcKNcKew@mail.gmail.com>

> I actually at one point started to implement FDB accessors to the RTL8366RB
> before I got sidetracked (for the same reasons of being able to do hardware
> offloading), here is how far I got before I got distracted:
> https://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-integrator.git/patch/?id=9941b129f91e92423803d6e2869022ffa66e9654
>
> You can see that it also has an L2 table albeit with 4 entries rather than 6,
> and an additional "CAM" (content adressable memory...) table that I don't quite
> understand.

I will look into the CAM table info in rtl8367c family.

> On Wed, Apr 1, 2026 at 1:01 AM Luiz Angelo Daros de Luca
> <luizluca@gmail.com> wrote:
>
> > +int rtl8365mb_l2_del_mc(struct realtek_priv *priv, u16 port,
> > +                       const unsigned char mac_addr[static ETH_ALEN],
> > +                       u16 vid)
> > +int rtl8365mb_l2_get_next_uc(struct realtek_priv *priv, u16 *addr, u16 port,
> > +                            struct rtl8365mb_l2_uc *uc);
> > +int rtl8365mb_l2_add_uc(struct realtek_priv *priv, u16 port,
> > +                       const unsigned char addr[static ETH_ALEN],
> > +                       u16 efid, u16 vid);
> > +int rtl8365mb_l2_del_uc(struct realtek_priv *priv, u16 port,
> > +                       const unsigned char addr[static ETH_ALEN],
> > +                       u16 efid, u16 vid);
> > +int rtl8365mb_l2_flush(struct realtek_priv *priv, int port, u16 vid);
> > +
> > +int rtl8365mb_l2_add_mc(struct realtek_priv *priv, u16 port,
> > +                       const unsigned char mac_addr[static ETH_ALEN],
> > +                       u16 vid);
> > +int rtl8365mb_l2_del_mc(struct realtek_priv *priv, u16 port,
> > +                       const unsigned char mac_addr[static ETH_ALEN],
> > +                       u16 vid);
>
> I think it would make sense to add these to struct realtek_ops and
>  make them available for all RTL8366 variants.

Agreed. I will add these to struct realtek_ops. I'll need to create a
generic replacement for struct rtl8365mb_l2_uc, but the rest of the
migration should be straightforward. For now, the efid argument can
simply be ignored by the RTL8366 implementation.

> Possibly it would even make sense to move rtl8365mb_table_query()
> to struct realtek_ops under the name .table_query and all of
> these helpers to rtl8366-core.c as rtl8366_l2_del_mc() etc
> just calling the per-chip table query variant. I'm not sure
> but you can perhaps see what makes most sense?

I suspect rtl8365mb_table_query() might be too complex to abstract
effectively without first seeing how the RTL8366 handles table
lookups, as hardware-specific behaviors can vary significantly here. I
suggest we implement it for the RTL8366 first; once we have a
reference point, we can discuss the best way to consolidate the logic.

> > +       struct mutex l2_lock;
>
> Move to struct realtek_priv, every chip will need an l2 lock.

Sure.

> > +static void rtl8365mb_port_fast_age(struct dsa_switch *ds, int port)
> > +static int rtl8365mb_port_fdb_add(struct dsa_switch *ds, int port,
> > +                                 const unsigned char *addr, u16 vid,
> > +                                 struct dsa_db db)
> > +static int rtl8365mb_port_fdb_del(struct dsa_switch *ds, int port,
> > +                                 const unsigned char *addr, u16 vid,
> > +                                 struct dsa_db db)
> > +static int rtl8365mb_port_fdb_dump(struct dsa_switch *ds, int port,
> > +                                  dsa_fdb_dump_cb_t *cb, void *data)
> > +static int rtl8365mb_port_mdb_add(struct dsa_switch *ds, int port,
> > +                                 const struct switchdev_obj_port_mdb *mdb,
> > +                                 struct dsa_db db)
> > +static int rtl8365mb_port_mdb_del(struct dsa_switch *ds, int port,
> > +                                 const struct switchdev_obj_port_mdb *mdb,
> > +                                 struct dsa_db db)
>
> I think you should rename all of these rtl8366_port_* and move them
> to rtl8366-core.c. They are generic.

Yes. Once rtl8365mb_l2_* is moved to realtek_ops, these functions
become generic wrappers and fit perfectly in rtl83xx.c.

> > @@ -2498,6 +2687,12 @@ static const struct dsa_switch_ops rtl8365mb_switch_ops = {
> >         .port_bridge_join = rtl8365mb_port_bridge_join,
> >         .port_bridge_leave = rtl8365mb_port_bridge_leave,
> >         .port_stp_state_set = rtl8365mb_port_stp_state_set,
> > +       .port_fast_age = rtl8365mb_port_fast_age,
>
> .port_fast_age = rtl8366_port_fast_age,

I will update the ops to use the new generics.

Regards,

Luiz

^ permalink raw reply

* RE: a bug in drivers/net/macsec.c ? (ssci endianness)
From: Karol Gajdos (Nokia) @ 2026-04-22  6:47 UTC (permalink / raw)
  To: Sabrina Dubroca; +Cc: netdev@vger.kernel.org
In-Reply-To: <aed1wCDC2Oh4eZ1h@krikkit>

Ok, so it's not a bug, but let's say an unusual agreement between user space and kernel,
as netlink generally uses the host byte order for encoding and decoding integers.
Anyhow thanks for the clarification and the great work done on MACsec.  

Karol

-----Original Message-----
From: Sabrina Dubroca <sd@queasysnail.net> 
Sent: Tuesday, April 21, 2026 3:04 PM
To: Karol Gajdos (Nokia) <karol.gajdos@nokia.com>
Cc: netdev@vger.kernel.org
Subject: Re: a bug in drivers/net/macsec.c ? (ssci endianness)


CAUTION: This is an external email. Please be very careful when clicking links or opening attachments. See the URL nok.it/ext for additional information.



2026-04-21, 11:37:53 +0000, Karol Gajdos (Nokia) wrote:
> Hi,
>
> there seems to be a bug in the function filling IV for the XPN case.
> Can you confirm please ?

We expect userspace to provide the SSCI in network byte order via the netlink API (same as SCI). As long as we're handling it that way consistently, which I think is the case, there is no bug.

--
Sabrina

^ permalink raw reply

* Re: [PATCH net v4 2/2] selftests/bpf: check epoll readiness during reuseport migration
From: Kuniyuki Iwashima @ 2026-04-22  6:40 UTC (permalink / raw)
  To: Zhenzhong Wu
  Cc: Tamir Duberstein, netdev, edumazet, ncardwell, davem, dsahern,
	kuba, pabeni, horms, shuah, linux-kernel, linux-kselftest
In-Reply-To: <CALgi0XnM49xUZm2-YAjPFoc_8j_F=y4gmVemGHacyH8aXeXaHw@mail.gmail.com>

On Tue, Apr 21, 2026 at 11:34 PM Zhenzhong Wu <jt26wzz@gmail.com> wrote:
>
> Thanks Tamir, I will fold this into v5 - there's already a precedent
> in socket_helpers.h, so I will just include it from there.

The test does not use cleanup in other places,
no need to mix them up.


>
> On Wed, Apr 22, 2026 at 11:04 AM Tamir Duberstein <tamird@kernel.org> wrote:
> >
> > On Tue, Apr 21, 2026 at 7:46 PM Zhenzhong Wu <jt26wzz@gmail.com> wrote:
> > >
> > > Inside migrate_dance(), add epoll checks around shutdown() to
> > > verify that the target listener is not ready before shutdown()
> > > and becomes ready immediately after shutdown() triggers migration.
> > >
> > > Cover TCP_ESTABLISHED and TCP_SYN_RECV. Exclude TCP_NEW_SYN_RECV
> > > as it depends on later handshake completion.
> > >
> > > Suggested-by: Kuniyuki Iwashima <kuniyu@google.com>
> > > Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
> > > Signed-off-by: Zhenzhong Wu <jt26wzz@gmail.com>
> > > ---
> > >  .../bpf/prog_tests/migrate_reuseport.c        | 49 ++++++++++++++++---
> > >  1 file changed, 42 insertions(+), 7 deletions(-)
> > >
> > > diff --git a/tools/testing/selftests/bpf/prog_tests/migrate_reuseport.c b/tools/testing/selftests/bpf/prog_tests/migrate_reuseport.c
> > > index 653b0a20f..c62907732 100644
> > > --- a/tools/testing/selftests/bpf/prog_tests/migrate_reuseport.c
> > > +++ b/tools/testing/selftests/bpf/prog_tests/migrate_reuseport.c
> > > @@ -7,24 +7,29 @@
> > >   *   3. call listen() for 1 server socket. (migration target)
> > >   *   4. update a map to migrate all child sockets
> > >   *        to the last server socket (migrate_map[cookie] = 4)
> > > - *   5. call shutdown() for first 4 server sockets
> > > + *   5. for TCP_ESTABLISHED and TCP_SYN_RECV cases, verify via epoll
> > > + *        that the last server socket is not ready before migration.
> > > + *   6. call shutdown() for first 4 server sockets
> > >   *        and migrate the requests in the accept queue
> > >   *        to the last server socket.
> > > - *   6. call listen() for the second server socket.
> > > - *   7. call shutdown() for the last server
> > > + *   7. for TCP_ESTABLISHED and TCP_SYN_RECV cases, verify via epoll
> > > + *        that the last server socket is ready after migration.
> > > + *   8. call listen() for the second server socket.
> > > + *   9. call shutdown() for the last server
> > >   *        and migrate the requests in the accept queue
> > >   *        to the second server socket.
> > > - *   8. call listen() for the last server.
> > > - *   9. call shutdown() for the second server
> > > + *  10. call listen() for the last server.
> > > + *  11. call shutdown() for the second server
> > >   *        and migrate the requests in the accept queue
> > >   *        to the last server socket.
> > > - *  10. call accept() for the last server socket.
> > > + *  12. call accept() for the last server socket.
> > >   *
> > >   * Author: Kuniyuki Iwashima <kuniyu@amazon.co.jp>
> > >   */
> > >
> > >  #include <bpf/bpf.h>
> > >  #include <bpf/libbpf.h>
> > > +#include <sys/epoll.h>
> > >
> > >  #include "test_progs.h"
> > >  #include "test_migrate_reuseport.skel.h"
> > > @@ -350,21 +355,51 @@ static int update_maps(struct migrate_reuseport_test_case *test_case,
> > >
> > >  static int migrate_dance(struct migrate_reuseport_test_case *test_case)
> > >  {
> > > +       struct epoll_event ev = {
> > > +               .events = EPOLLIN,
> > > +       };
> > > +       int epoll = -1, nfds;
> > >         int i, err;
> > >
> > > +       if (test_case->state != BPF_TCP_NEW_SYN_RECV) {
> > > +               epoll = epoll_create1(0);
> > > +               if (!ASSERT_NEQ(epoll, -1, "epoll_create1"))
> > > +                       return -1;
> > > +
> > > +               ev.data.fd = test_case->servers[MIGRATED_TO];
> > > +               if (!ASSERT_OK(epoll_ctl(epoll, EPOLL_CTL_ADD,
> > > +                                        test_case->servers[MIGRATED_TO], &ev),
> > > +                              "epoll_ctl"))
> > > +                       goto close_epoll;
> > > +
> > > +               nfds = epoll_wait(epoll, &ev, 1, 0);
> > > +               if (!ASSERT_EQ(nfds, 0, "epoll_wait 1"))
> > > +                       goto close_epoll;
> > > +       }
> > > +
> > >         /* Migrate TCP_ESTABLISHED and TCP_SYN_RECV requests
> > >          * to the last listener based on eBPF.
> > >          */
> > >         for (i = 0; i < MIGRATED_TO; i++) {
> > >                 err = shutdown(test_case->servers[i], SHUT_RDWR);
> > >                 if (!ASSERT_OK(err, "shutdown"))
> > > -                       return -1;
> > > +                       goto close_epoll;
> > >         }
> > >
> > >         /* No dance for TCP_NEW_SYN_RECV to migrate based on eBPF */
> > >         if (test_case->state == BPF_TCP_NEW_SYN_RECV)
> > >                 return 0;
> > >
> > > +       nfds = epoll_wait(epoll, &ev, 1, 0);
> > > +       if (!ASSERT_EQ(nfds, 1, "epoll_wait 2")) {
> > > +close_epoll:
> > > +               if (epoll >= 0)
> > > +                       close(epoll);
> > > +               return -1;
> > > +       }
> >
> > I think you can avoid this goto using `__attribute__((cleanup(...))`:
> >
> >   static void close_fd(int *fd)
> >   {
> >         if (*fd >= 0)
> >                 close(*fd);
> >   }
> >
> >   #define __close_fd __attribute__((cleanup(close_fd)))
> >
> > then in the test:
> >
> > __close_fd int epoll = -1;
> >
> > there's an example of this in
> > tools/testing/selftests/bpf/prog_tests/socket_helpers.h.

^ permalink raw reply

* Re: [PATCH 02/23] sched/isolation: Enhance housekeeping_update() to support updating more than one HK cpumask
From: Chen Ridong @ 2026-04-22  6:39 UTC (permalink / raw)
  To: Waiman Long, Tejun Heo, Johannes Weiner, Michal Koutný,
	Jonathan Corbet, Shuah Khan, Catalin Marinas, Will Deacon,
	K. Y. Srinivasan, Haiyang Zhang, Wei Liu, Dexuan Cui, Long Li,
	Guenter Roeck, Frederic Weisbecker, Paul E. McKenney,
	Neeraj Upadhyay, Joel Fernandes, Josh Triplett, Boqun Feng,
	Uladzislau Rezki, Steven Rostedt, Mathieu Desnoyers,
	Lai Jiangshan, Zqiang, Anna-Maria Behnsen, Ingo Molnar,
	Thomas Gleixner, Peter Zijlstra, Juri Lelli, Vincent Guittot,
	Dietmar Eggemann, Ben Segall, Mel Gorman, Valentin Schneider,
	K Prateek Nayak, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Simon Horman
  Cc: cgroups, linux-doc, linux-kernel, linux-arm-kernel, linux-hyperv,
	linux-hwmon, rcu, netdev, linux-kselftest, Costa Shulyupin,
	Qiliang Yuan
In-Reply-To: <20260421030351.281436-3-longman@redhat.com>



On 2026/4/21 11:03, Waiman Long wrote:
> The housekeeping_update() function currently allows update to the
> HK_TYPE_DOMAIN cpumask only. As we are going to enable dynamic
> modification of the other housekeeping cpumasks, we need to extend
> it to support passing in the information about the HK cpumask(s) to
> be updated.  In cases where some HK cpumasks happen to be the same,
> it will be more efficient to update multiple HK cpumasks in one single
> call instead of calling it multiple times. Extend housekeeping_update()
> to support that as well.
> 
> Also add the restriction that passed in isolated cpumask parameter
> of housekeeping_update() must include all the CPUs isolated at boot
> time. This is currently the case for cpuset anyway.
> 
> Signed-off-by: Waiman Long <longman@redhat.com>
> ---
>  include/linux/sched/isolation.h |  2 +-
>  kernel/cgroup/cpuset.c          |  2 +-
>  kernel/sched/isolation.c        | 99 +++++++++++++++++++++++----------
>  3 files changed, 71 insertions(+), 32 deletions(-)
> 
> diff --git a/include/linux/sched/isolation.h b/include/linux/sched/isolation.h
> index d1707f121e20..a17f16e0156e 100644
> --- a/include/linux/sched/isolation.h
> +++ b/include/linux/sched/isolation.h
> @@ -51,7 +51,7 @@ extern const struct cpumask *housekeeping_cpumask(enum hk_type type);
>  extern bool housekeeping_enabled(enum hk_type type);
>  extern void housekeeping_affine(struct task_struct *t, enum hk_type type);
>  extern bool housekeeping_test_cpu(int cpu, enum hk_type type);
> -extern int housekeeping_update(struct cpumask *isol_mask);
> +extern int housekeeping_update(struct cpumask *isol_mask, unsigned long flags);
>  extern void __init housekeeping_init(void);
>  
>  #else
> diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
> index 1335e437098e..a4eccb0ec0d1 100644
> --- a/kernel/cgroup/cpuset.c
> +++ b/kernel/cgroup/cpuset.c
> @@ -1354,7 +1354,7 @@ static void cpuset_update_sd_hk_unlock(void)
>  		 */
>  		mutex_unlock(&cpuset_mutex);
>  		cpus_read_unlock();
> -		WARN_ON_ONCE(housekeeping_update(isolated_hk_cpus));
> +		WARN_ON_ONCE(housekeeping_update(isolated_hk_cpus, BIT(HK_TYPE_DOMAIN)));
>  		mutex_unlock(&cpuset_top_mutex);
>  	} else {
>  		cpuset_full_unlock();
> diff --git a/kernel/sched/isolation.c b/kernel/sched/isolation.c
> index 9ec9ae510dc7..965d6f8fe344 100644
> --- a/kernel/sched/isolation.c
> +++ b/kernel/sched/isolation.c
> @@ -120,48 +120,87 @@ bool housekeeping_test_cpu(int cpu, enum hk_type type)
>  }
>  EXPORT_SYMBOL_GPL(housekeeping_test_cpu);
>  
> -int housekeeping_update(struct cpumask *isol_mask)
> -{
> -	struct cpumask *trial, *old = NULL;
> -	int err;
> +/* HK type processing table */
> +static struct {
> +	int type;
> +	int boot_type;
> +} hk_types[] = {
> +	{ HK_TYPE_DOMAIN,       HK_TYPE_DOMAIN_BOOT	  },
> +	{ HK_TYPE_MANAGED_IRQ,  HK_TYPE_MANAGED_IRQ_BOOT  },
> +	{ HK_TYPE_KERNEL_NOISE, HK_TYPE_KERNEL_NOISE_BOOT }
> +};
>  
> -	trial = kmalloc(cpumask_size(), GFP_KERNEL);
> -	if (!trial)
> -		return -ENOMEM;
> +#define HK_TYPE_CNT	ARRAY_SIZE(hk_types)
>  
> -	cpumask_andnot(trial, housekeeping_cpumask(HK_TYPE_DOMAIN_BOOT), isol_mask);
> -	if (!cpumask_intersects(trial, cpu_online_mask)) {
> -		kfree(trial);
> -		return -EINVAL;
> +int housekeeping_update(struct cpumask *isol_mask, unsigned long flags)
> +{
> +	struct cpumask *trial[HK_TYPE_CNT];
> +	int i, err = 0;
> +
> +	for (i = 0; i < HK_TYPE_CNT; i++) {
> +		int type = hk_types[i].type;
> +		int boot = hk_types[i].boot_type;
> +
> +		trial[i] = NULL;
> +		if (flags & BIT(type)) {
> +			trial[i] = kmalloc(cpumask_size(), GFP_KERNEL);
> +			if (!trial[i]) {
> +				err = -ENOMEM;
> +				goto out;
> +			}
> +			/*
> +			 * The new HK cpumask must be a subset of its boot
> +			 * cpumask.
> +			 */
> +			cpumask_andnot(trial[i], cpu_possible_mask, isol_mask);
> +			if (!cpumask_intersects(trial[i], cpu_online_mask) ||
> +			    !cpumask_subset(trial[i], housekeeping_cpumask(boot))) {
> +				i++;
> +				err = -EINVAL;
> +				goto out;
> +			}
> +		}
>  	}
>  

The i++ here is confusing. Wouldn't it be more readable to just use
kfree(trial[i]) and then break out?

>  	if (!housekeeping.flags)
>  		static_branch_enable(&housekeeping_overridden);
>  
> -	if (housekeeping.flags & HK_FLAG_DOMAIN)
> -		old = housekeeping_cpumask_dereference(HK_TYPE_DOMAIN);
> -	else
> -		WRITE_ONCE(housekeeping.flags, housekeeping.flags | HK_FLAG_DOMAIN);
> -	rcu_assign_pointer(housekeeping.cpumasks[HK_TYPE_DOMAIN], trial);
> -
> -	synchronize_rcu();
> -
> -	pci_probe_flush_workqueue();
> -	mem_cgroup_flush_workqueue();
> -	vmstat_flush_workqueue();
> +	for (i = 0; i < HK_TYPE_CNT; i++) {
> +		int type =  hk_types[i].type;
> +		struct cpumask *old;
>  
> -	err = workqueue_unbound_housekeeping_update(housekeeping_cpumask(HK_TYPE_DOMAIN));
> -	WARN_ON_ONCE(err < 0);
> +		if (!trial[i])
> +			continue;
> +		old = NULL;
> +		if (housekeeping.flags & BIT(type))
> +			old = housekeeping_cpumask_dereference(type);
> +		rcu_assign_pointer(housekeeping.cpumasks[type], trial[i]);
> +		trial[i] = old;
> +	}
>  
> -	err = tmigr_isolated_exclude_cpumask(isol_mask);
> -	WARN_ON_ONCE(err < 0);
> +	if ((housekeeping.flags & flags) != flags)
> +		WRITE_ONCE(housekeeping.flags, housekeeping.flags | flags);
>  
> -	err = kthreads_update_housekeeping();
> -	WARN_ON_ONCE(err < 0);
> +	synchronize_rcu();
>  
> -	kfree(old);
> +	if (flags & HK_FLAG_DOMAIN) {
> +		/*
> +		 * HK_TYPE_DOMAIN specific callbacks
> +		 */
> +		pci_probe_flush_workqueue();
> +		mem_cgroup_flush_workqueue();
> +		vmstat_flush_workqueue();
> +
> +		WARN_ON_ONCE(workqueue_unbound_housekeeping_update(
> +				housekeeping_cpumask(HK_TYPE_DOMAIN)) < 0);
> +		WARN_ON_ONCE(tmigr_isolated_exclude_cpumask(isol_mask) < 0);
> +		WARN_ON_ONCE(kthreads_update_housekeeping() < 0);
> +	}
>  
> -	return 0;
> +out:
> +	while (--i >= 0)
> +		kfree(trial[i]);
> +	return err;
>  }
>  
>  void __init housekeeping_init(void)

-- 
Best regards,
Ridong


^ permalink raw reply

* Re: [PATCH net v4 2/2] selftests/bpf: check epoll readiness during reuseport migration
From: Zhenzhong Wu @ 2026-04-22  6:34 UTC (permalink / raw)
  To: Tamir Duberstein
  Cc: netdev, edumazet, ncardwell, kuniyu, davem, dsahern, kuba, pabeni,
	horms, shuah, linux-kernel, linux-kselftest
In-Reply-To: <CAJ-ks9=FKMoczH+Z=GQ7C40T42=zdknYzzHCa8UVFOtq2H69cw@mail.gmail.com>

Thanks Tamir, I will fold this into v5 - there's already a precedent
in socket_helpers.h, so I will just include it from there.

On Wed, Apr 22, 2026 at 11:04 AM Tamir Duberstein <tamird@kernel.org> wrote:
>
> On Tue, Apr 21, 2026 at 7:46 PM Zhenzhong Wu <jt26wzz@gmail.com> wrote:
> >
> > Inside migrate_dance(), add epoll checks around shutdown() to
> > verify that the target listener is not ready before shutdown()
> > and becomes ready immediately after shutdown() triggers migration.
> >
> > Cover TCP_ESTABLISHED and TCP_SYN_RECV. Exclude TCP_NEW_SYN_RECV
> > as it depends on later handshake completion.
> >
> > Suggested-by: Kuniyuki Iwashima <kuniyu@google.com>
> > Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
> > Signed-off-by: Zhenzhong Wu <jt26wzz@gmail.com>
> > ---
> >  .../bpf/prog_tests/migrate_reuseport.c        | 49 ++++++++++++++++---
> >  1 file changed, 42 insertions(+), 7 deletions(-)
> >
> > diff --git a/tools/testing/selftests/bpf/prog_tests/migrate_reuseport.c b/tools/testing/selftests/bpf/prog_tests/migrate_reuseport.c
> > index 653b0a20f..c62907732 100644
> > --- a/tools/testing/selftests/bpf/prog_tests/migrate_reuseport.c
> > +++ b/tools/testing/selftests/bpf/prog_tests/migrate_reuseport.c
> > @@ -7,24 +7,29 @@
> >   *   3. call listen() for 1 server socket. (migration target)
> >   *   4. update a map to migrate all child sockets
> >   *        to the last server socket (migrate_map[cookie] = 4)
> > - *   5. call shutdown() for first 4 server sockets
> > + *   5. for TCP_ESTABLISHED and TCP_SYN_RECV cases, verify via epoll
> > + *        that the last server socket is not ready before migration.
> > + *   6. call shutdown() for first 4 server sockets
> >   *        and migrate the requests in the accept queue
> >   *        to the last server socket.
> > - *   6. call listen() for the second server socket.
> > - *   7. call shutdown() for the last server
> > + *   7. for TCP_ESTABLISHED and TCP_SYN_RECV cases, verify via epoll
> > + *        that the last server socket is ready after migration.
> > + *   8. call listen() for the second server socket.
> > + *   9. call shutdown() for the last server
> >   *        and migrate the requests in the accept queue
> >   *        to the second server socket.
> > - *   8. call listen() for the last server.
> > - *   9. call shutdown() for the second server
> > + *  10. call listen() for the last server.
> > + *  11. call shutdown() for the second server
> >   *        and migrate the requests in the accept queue
> >   *        to the last server socket.
> > - *  10. call accept() for the last server socket.
> > + *  12. call accept() for the last server socket.
> >   *
> >   * Author: Kuniyuki Iwashima <kuniyu@amazon.co.jp>
> >   */
> >
> >  #include <bpf/bpf.h>
> >  #include <bpf/libbpf.h>
> > +#include <sys/epoll.h>
> >
> >  #include "test_progs.h"
> >  #include "test_migrate_reuseport.skel.h"
> > @@ -350,21 +355,51 @@ static int update_maps(struct migrate_reuseport_test_case *test_case,
> >
> >  static int migrate_dance(struct migrate_reuseport_test_case *test_case)
> >  {
> > +       struct epoll_event ev = {
> > +               .events = EPOLLIN,
> > +       };
> > +       int epoll = -1, nfds;
> >         int i, err;
> >
> > +       if (test_case->state != BPF_TCP_NEW_SYN_RECV) {
> > +               epoll = epoll_create1(0);
> > +               if (!ASSERT_NEQ(epoll, -1, "epoll_create1"))
> > +                       return -1;
> > +
> > +               ev.data.fd = test_case->servers[MIGRATED_TO];
> > +               if (!ASSERT_OK(epoll_ctl(epoll, EPOLL_CTL_ADD,
> > +                                        test_case->servers[MIGRATED_TO], &ev),
> > +                              "epoll_ctl"))
> > +                       goto close_epoll;
> > +
> > +               nfds = epoll_wait(epoll, &ev, 1, 0);
> > +               if (!ASSERT_EQ(nfds, 0, "epoll_wait 1"))
> > +                       goto close_epoll;
> > +       }
> > +
> >         /* Migrate TCP_ESTABLISHED and TCP_SYN_RECV requests
> >          * to the last listener based on eBPF.
> >          */
> >         for (i = 0; i < MIGRATED_TO; i++) {
> >                 err = shutdown(test_case->servers[i], SHUT_RDWR);
> >                 if (!ASSERT_OK(err, "shutdown"))
> > -                       return -1;
> > +                       goto close_epoll;
> >         }
> >
> >         /* No dance for TCP_NEW_SYN_RECV to migrate based on eBPF */
> >         if (test_case->state == BPF_TCP_NEW_SYN_RECV)
> >                 return 0;
> >
> > +       nfds = epoll_wait(epoll, &ev, 1, 0);
> > +       if (!ASSERT_EQ(nfds, 1, "epoll_wait 2")) {
> > +close_epoll:
> > +               if (epoll >= 0)
> > +                       close(epoll);
> > +               return -1;
> > +       }
>
> I think you can avoid this goto using `__attribute__((cleanup(...))`:
>
>   static void close_fd(int *fd)
>   {
>         if (*fd >= 0)
>                 close(*fd);
>   }
>
>   #define __close_fd __attribute__((cleanup(close_fd)))
>
> then in the test:
>
> __close_fd int epoll = -1;
>
> there's an example of this in
> tools/testing/selftests/bpf/prog_tests/socket_helpers.h.

^ permalink raw reply

* Re: [PATCH] smb: smbdirect: move fs/smb/common/smbdirect/ to fs/smb/smbdirect/
From: Christoph Hellwig @ 2026-04-22  6:31 UTC (permalink / raw)
  To: Stefan Metzmacher
  Cc: linux-cifs, samba-technical, Linus Torvalds, Steve French,
	Tom Talpey, Long Li, Namjae Jeon, linux-rdma, netdev
In-Reply-To: <20260419192018.3046449-1-metze@samba.org>

> diff --git a/fs/smb/Makefile b/fs/smb/Makefile
> index 9a1bf59a1a65..353b1c2eefc4 100644
> --- a/fs/smb/Makefile
> +++ b/fs/smb/Makefile
> @@ -1,5 +1,6 @@
>  # SPDX-License-Identifier: GPL-2.0
>  
>  obj-$(CONFIG_SMBFS)		+= common/
> +obj-$(CONFIG_SMBDIRECT)		+= smbdirect/

Why is this not in net/smbdirect/ or driver/infiniband/ulp/smdirect?

As far as I can tell there is zero file system logic in this code.

> -#include "../common/smbdirect/smbdirect_public.h"
> +#include "../smbdirect/public.h"

And all these relative includes suggest you really want a
include/linux/smdirect/ instead.

While we're at it: __SMBDIRECT_EXPORT_SYMBOL__ is really odd.
One thing is the __ pre- and postfix that make it look weird.

The other is that EXPORT_SYMBOL_FOR_MODULES is for very specific
symbols that really should not exported.  What this warrants instead
is a normal EXPORT_SYMBOL_NS_GPL.


^ permalink raw reply

* Re: [PATCH net 14/18] drivers: net: xircom: xirc2ps: Remove this driver
From: Michael Fritscher @ 2026-04-22  6:21 UTC (permalink / raw)
  To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Simon Horman, Jonathan Corbet, Shuah Khan
  Cc: linux-kernel, netdev, linux-doc, Andrew Lunn

Good day,

actually, I do use Xircom PCMCIA network cards (yes, the 16 bit ones) on 
Lenovo X60/X61 laptops as a second LAN card for server maintenances with 
current 64 bit distros (e.g. Debian Trixie, which I plan to update to 
Trixie+1 when available). Why? Because I have them and they are working ;-)

Best regards
Michael Fritscher


^ permalink raw reply

* Re: [PATCH] wifi: mac80211: check ieee80211_rx_data_set_link return in pubsta MLO path
From: Johannes Berg @ 2026-04-22  6:27 UTC (permalink / raw)
  To: Michael Bommarito, linux-wireless
  Cc: Felix Fietkau, Benjamin Berg, netdev, linux-kernel
In-Reply-To: <20260422000651.4184602-1-michael.bommarito@gmail.com>

On Tue, 2026-04-21 at 20:06 -0400, Michael Bommarito wrote:

> Benjamin Berg's 2026-02 RFC v2 "wifi: mac80211: refactor RX
> link_id and station handling"
> (20260223133818.9f5550ab445f.I...@changeid) touches the same
> code and may supersede or subsume this patch; happy to fold /
> rebase / drop.

Yeah, Benjamin, what's up with that :)

OTOH we perhaps wants this patch in wireless, and then yours in
wireless-next.

johannes

^ permalink raw reply

* Re: [PATCH v1 05/11] drm/xe/sysctrl: Add system controller interrupt handler
From: Raag Jadav @ 2026-04-22  6:25 UTC (permalink / raw)
  To: Tauro, Riana
  Cc: intel-xe, dri-devel, netdev, simona.vetter, airlied, kuba,
	lijo.lazar, Hawking.Zhang, davem, pabeni, edumazet, maarten,
	zachary.mckevitt, rodrigo.vivi, michal.wajdeczko, matthew.d.roper,
	umesh.nerlige.ramappa, mallesh.koujalagi, soham.purkait,
	anoop.c.vijay, aravind.iddamsetty
In-Reply-To: <c5ae7bab-ee42-430f-abf1-e062439c1356@intel.com>

On Wed, Apr 22, 2026 at 11:25:44AM +0530, Tauro, Riana wrote:
> On 4/18/2026 2:46 AM, Raag Jadav wrote:
> > Add system controller interrupt handler which is denoted by 11th bit in
> > GFX master interrupt register. While at it, add worker for scheduling
> > system controller work.
> 
> Why do we need this series in the threshold patch. From what i see, we need
> only structures
> Can't we only redefine those here?
> 
> I know you will have to rebase again once any patch is merged. But this is
> unnecessary noise
> for the drm patch.

We have threshold crossed event so I thought it was relevant here. We can
merge it independently if you're okay with it.

Raag

> > Co-developed-by: Soham Purkait <soham.purkait@intel.com>
> > Signed-off-by: Soham Purkait <soham.purkait@intel.com>
> > Signed-off-by: Raag Jadav <raag.jadav@intel.com>
> > Reviewed-by: Mallesh Koujalagi <mallesh.koujalagi@intel.com>
> > Reviewed-by: Riana Tauro <riana.tauro@intel.com>
> > ---
> >   drivers/gpu/drm/xe/regs/xe_irq_regs.h |  1 +
> >   drivers/gpu/drm/xe/xe_irq.c           |  2 ++
> >   drivers/gpu/drm/xe/xe_sysctrl.c       | 35 +++++++++++++++++++++------
> >   drivers/gpu/drm/xe/xe_sysctrl.h       |  1 +
> >   drivers/gpu/drm/xe/xe_sysctrl_types.h |  4 +++
> >   5 files changed, 36 insertions(+), 7 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/xe/regs/xe_irq_regs.h b/drivers/gpu/drm/xe/regs/xe_irq_regs.h
> > index 9d74f454d3ff..1d6b976c4de0 100644
> > --- a/drivers/gpu/drm/xe/regs/xe_irq_regs.h
> > +++ b/drivers/gpu/drm/xe/regs/xe_irq_regs.h
> > @@ -22,6 +22,7 @@
> >   #define   DISPLAY_IRQ				REG_BIT(16)
> >   #define   SOC_H2DMEMINT_IRQ			REG_BIT(13)
> >   #define   I2C_IRQ				REG_BIT(12)
> > +#define   SYSCTRL_IRQ				REG_BIT(11)
> >   #define   GT_DW_IRQ(x)				REG_BIT(x)
> >   /*
> > diff --git a/drivers/gpu/drm/xe/xe_irq.c b/drivers/gpu/drm/xe/xe_irq.c
> > index 9a775c6588dc..e9f0b3cad06d 100644
> > --- a/drivers/gpu/drm/xe/xe_irq.c
> > +++ b/drivers/gpu/drm/xe/xe_irq.c
> > @@ -24,6 +24,7 @@
> >   #include "xe_mmio.h"
> >   #include "xe_pxp.h"
> >   #include "xe_sriov.h"
> > +#include "xe_sysctrl.h"
> >   #include "xe_tile.h"
> >   /*
> > @@ -525,6 +526,7 @@ static irqreturn_t dg1_irq_handler(int irq, void *arg)
> >   				xe_heci_csc_irq_handler(xe, master_ctl);
> >   			xe_display_irq_handler(xe, master_ctl);
> >   			xe_i2c_irq_handler(xe, master_ctl);
> > +			xe_sysctrl_irq_handler(xe, master_ctl);
> >   			xe_mert_irq_handler(xe, master_ctl);
> >   			gu_misc_iir = gu_misc_irq_ack(xe, master_ctl);
> >   		}
> > diff --git a/drivers/gpu/drm/xe/xe_sysctrl.c b/drivers/gpu/drm/xe/xe_sysctrl.c
> > index 2bcef304eb9a..7de3e73bd8e0 100644
> > --- a/drivers/gpu/drm/xe/xe_sysctrl.c
> > +++ b/drivers/gpu/drm/xe/xe_sysctrl.c
> > @@ -8,6 +8,7 @@
> >   #include <drm/drm_managed.h>
> > +#include "regs/xe_irq_regs.h"
> >   #include "regs/xe_sysctrl_regs.h"
> >   #include "xe_device.h"
> >   #include "xe_mmio.h"
> > @@ -30,10 +31,16 @@
> >   static void sysctrl_fini(void *arg)
> >   {
> >   	struct xe_device *xe = arg;
> > +	struct xe_sysctrl *sc = &xe->sc;
> > +	disable_work_sync(&sc->work);
> >   	xe->soc_remapper.set_sysctrl_region(xe, 0);
> >   }
> > +static void xe_sysctrl_work(struct work_struct *work)
> > +{
> > +}
> > +
> >   /**
> >    * xe_sysctrl_init() - Initialize System Controller subsystem
> >    * @xe: xe device instance
> > @@ -55,12 +62,6 @@ int xe_sysctrl_init(struct xe_device *xe)
> >   	if (!xe->info.has_sysctrl)
> >   		return 0;
> > -	xe->soc_remapper.set_sysctrl_region(xe, SYSCTRL_MAILBOX_INDEX);
> > -
> > -	ret = devm_add_action_or_reset(xe->drm.dev, sysctrl_fini, xe);
> > -	if (ret)
> > -		return ret;
> > -
> >   	sc->mmio = devm_kzalloc(xe->drm.dev, sizeof(*sc->mmio), GFP_KERNEL);
> >   	if (!sc->mmio)
> >   		return -ENOMEM;
> > @@ -73,9 +74,29 @@ int xe_sysctrl_init(struct xe_device *xe)
> >   	if (ret)
> >   		return ret;
> > +	xe->soc_remapper.set_sysctrl_region(xe, SYSCTRL_MAILBOX_INDEX);
> >   	xe_sysctrl_mailbox_init(sc);
> > +	INIT_WORK(&sc->work, xe_sysctrl_work);
> > -	return 0;
> > +	return devm_add_action_or_reset(xe->drm.dev, sysctrl_fini, xe);
> > +}
> > +
> > +/**
> > + * xe_sysctrl_irq_handler() - Handler for System Controller interrupts
> > + * @xe: xe device instance
> > + * @master_ctl: interrupt register
> > + *
> > + * Handle interrupts generated by System Controller.
> > + */
> > +void xe_sysctrl_irq_handler(struct xe_device *xe, u32 master_ctl)
> > +{
> > +	struct xe_sysctrl *sc = &xe->sc;
> > +
> > +	if (!xe->info.has_sysctrl || !sc->work.func)
> > +		return;
> > +
> > +	if (master_ctl & SYSCTRL_IRQ)
> > +		schedule_work(&sc->work);
> >   }
> >   /**
> > diff --git a/drivers/gpu/drm/xe/xe_sysctrl.h b/drivers/gpu/drm/xe/xe_sysctrl.h
> > index f3b0f3716b2f..f7469bfc9324 100644
> > --- a/drivers/gpu/drm/xe/xe_sysctrl.h
> > +++ b/drivers/gpu/drm/xe/xe_sysctrl.h
> > @@ -17,6 +17,7 @@ static inline struct xe_device *sc_to_xe(struct xe_sysctrl *sc)
> >   }
> >   int xe_sysctrl_init(struct xe_device *xe);
> > +void xe_sysctrl_irq_handler(struct xe_device *xe, u32 master_ctl);
> >   void xe_sysctrl_pm_resume(struct xe_device *xe);
> >   #endif
> > diff --git a/drivers/gpu/drm/xe/xe_sysctrl_types.h b/drivers/gpu/drm/xe/xe_sysctrl_types.h
> > index 8217f6befe70..5f408d6491ef 100644
> > --- a/drivers/gpu/drm/xe/xe_sysctrl_types.h
> > +++ b/drivers/gpu/drm/xe/xe_sysctrl_types.h
> > @@ -8,6 +8,7 @@
> >   #include <linux/mutex.h>
> >   #include <linux/types.h>
> > +#include <linux/workqueue_types.h>
> >   struct xe_mmio;
> > @@ -27,6 +28,9 @@ struct xe_sysctrl {
> >   	/** @phase_bit: Message boundary phase toggle bit (0 or 1) */
> >   	bool phase_bit;
> > +
> > +	/** @work: Pending events worker */
> > +	struct work_struct work;
> >   };
> >   #endif

^ permalink raw reply

* Re: [PATCH v1 02/11] drm/ras: Introduce get-error-threshold
From: Raag Jadav @ 2026-04-22  6:21 UTC (permalink / raw)
  To: Tauro, Riana
  Cc: intel-xe, dri-devel, netdev, simona.vetter, airlied, kuba,
	lijo.lazar, Hawking.Zhang, davem, pabeni, edumazet, maarten,
	zachary.mckevitt, rodrigo.vivi, michal.wajdeczko, matthew.d.roper,
	umesh.nerlige.ramappa, mallesh.koujalagi, soham.purkait,
	anoop.c.vijay, aravind.iddamsetty
In-Reply-To: <0c855393-be55-497d-aabe-fbe72e37321f@intel.com>

On Wed, Apr 22, 2026 at 11:19:36AM +0530, Tauro, Riana wrote:
> On 4/18/2026 2:46 AM, Raag Jadav wrote:
> > Add get-error-threshold command support which allows querying threshold
> > value of the error. Threshold in RAS context means the number of errors
> > the hardware is expected to accumulate before it raises them to software.
> > This is to have a fine grained control over error notifications that are
> > raised by the hardware.
> > 
> > Signed-off-by: Raag Jadav <raag.jadav@intel.com>
> > ---
> >   Documentation/gpu/drm-ras.rst            |   8 ++
> >   Documentation/netlink/specs/drm_ras.yaml |  37 ++++++++
> >   drivers/gpu/drm/drm_ras.c                | 103 +++++++++++++++++++++++
> >   drivers/gpu/drm/drm_ras_nl.c             |  13 +++
> >   drivers/gpu/drm/drm_ras_nl.h             |   2 +
> >   include/drm/drm_ras.h                    |  14 +++
> >   include/uapi/drm/drm_ras.h               |  11 +++
> >   7 files changed, 188 insertions(+)
> > 
> > diff --git a/Documentation/gpu/drm-ras.rst b/Documentation/gpu/drm-ras.rst
> > index 70b246a78fc8..6443dfd1677f 100644
> > --- a/Documentation/gpu/drm-ras.rst
> > +++ b/Documentation/gpu/drm-ras.rst
> > @@ -52,6 +52,8 @@ User space tools can:
> >     as a parameter.
> >   * Query specific error counter values with the ``get-error-counter`` command, using both
> >     ``node-id`` and ``error-id`` as parameters.
> > +* Query specific error threshold value with the ``get-error-threshold`` command, using both
> > +  ``node-id`` and ``error-id`` as parameters.
> Also define what is a thresold. How can it be used?

Sure, I'll append commit message description here.

> >   YAML-based Interface
> >   --------------------
> > @@ -101,3 +103,9 @@ Example: Query an error counter for a given node
> >       sudo ynl --family drm_ras --do get-error-counter --json '{"node-id":0, "error-id":1}'
> >       {'error-id': 1, 'error-name': 'error_name1', 'error-value': 0}
> > +Example: Query threshold value of a given error
> > +
> > +.. code-block:: bash
> > +
> > +    sudo ynl --family drm_ras --do get-error-threshold --json '{"node-id":0, "error-id":1}'
> > +    {'error-id': 1, 'error-name': 'error_name1', 'error-threshold': 0}
> > diff --git a/Documentation/netlink/specs/drm_ras.yaml b/Documentation/netlink/specs/drm_ras.yaml
> > index 79af25dac3c5..95a939fb987d 100644
> > --- a/Documentation/netlink/specs/drm_ras.yaml
> > +++ b/Documentation/netlink/specs/drm_ras.yaml
> > @@ -69,6 +69,25 @@ attribute-sets:
> >           name: error-value
> >           type: u32
> >           doc: Current value of the requested error counter.
> > +  -
> > +    name: error-threshold-attrs
> > +    attributes:
> > +      -
> > +        name: node-id
> > +        type: u32
> > +        doc: Node ID targeted by this operation.
> > +      -
> > +        name: error-id
> > +        type: u32
> > +        doc: Unique identifier for a specific error within the node.
> > +      -
> > +        name: error-name
> > +        type: string
> > +        doc: Name of the error.
> > +      -
> > +        name: error-threshold
> > +        type: u32
> > +        doc: Threshold value of the error.
> >   operations:
> >     list:
> > @@ -113,3 +132,21 @@ operations:
> >               - node-id
> >           reply:
> >             attributes: *errorinfo
> > +    -
> > +      name: get-error-threshold
> > +      doc: >-
> > +           Retrieve threshold value of the error.
> > +           The response includes the id, the name, and current threshold
> > +           value of the error.
> > +      attribute-set: error-threshold-attrs
> > +      flags: [admin-perm]
> > +      do:
> > +        request:
> > +          attributes:
> > +            - node-id
> > +            - error-id
> > +        reply:
> > +          attributes:
> > +            - error-id
> > +            - error-name
> > +            - error-threshold
> > diff --git a/drivers/gpu/drm/drm_ras.c b/drivers/gpu/drm/drm_ras.c
> > index 1f7435d60f11..d2d853d5d69c 100644
> > --- a/drivers/gpu/drm/drm_ras.c
> > +++ b/drivers/gpu/drm/drm_ras.c
> > @@ -37,6 +37,10 @@
> >    *    Returns all counters of a node if only Node ID is provided or specific
> >    *    error counters.
> >    *
> > + * 3. GET_ERROR_THRESHOLD: Query threshold value of the error.
> > + *    Userspace must provide Node ID and Error ID.
> > + *    Returns the threshold value of a specific error.
> > + *
> >    * Node registration:
> >    *
> >    * - drm_ras_node_register(): Registers a new node and assigns
> > @@ -66,6 +70,8 @@
> >    *   operation, fetching all counters from a specific node.
> >    * - drm_ras_nl_get_error_counter_doit(): Implements the GET_ERROR_COUNTER doit
> >    *   operation, fetching a counter value from a specific node.
> > + * - drm_ras_nl_get_error_threshold_doit(): Implements the GET_ERROR_THRESHOLD doit
> > + *   operation, fetching the threshold value of a specific error.
> >    */
> >   static DEFINE_XARRAY_ALLOC(drm_ras_xa);
> > @@ -162,6 +168,22 @@ static int get_node_error_counter(u32 node_id, u32 error_id,
> >   	return node->query_error_counter(node, error_id, name, value);
> >   }
> > +static int get_node_error_threshold(u32 node_id, u32 error_id,
> > +				    const char **name, u32 *value)
> > +{
> > +	struct drm_ras_node *node;
> > +
> > +	node = xa_load(&drm_ras_xa, node_id);
> > +	if (!node || !node->query_error_threshold)
> > +		return -ENOENT;
> 
> For the absence of the function, return -EOPNOTSUPP

Works for me, but then it should be consistent for all commands.

> > +
> > +	if (error_id < node->error_counter_range.first ||
> > +	    error_id > node->error_counter_range.last)
> > +		return -EINVAL;
> > +
> > +	return node->query_error_threshold(node, error_id, name, value);
> > +}
> > +
> >   static int msg_reply_counter_value(struct sk_buff *msg, u32 error_id,
> >   				   const char *error_name, u32 value)
> >   {
> > @@ -180,6 +202,24 @@ static int msg_reply_counter_value(struct sk_buff *msg, u32 error_id,
> >   			   value);
> >   }
> > +static int msg_reply_threshold_value(struct sk_buff *msg, u32 error_id,
> > +				     const char *error_name, u32 value)
> > +{
> > +	int ret;
> > +
> > +	ret = nla_put_u32(msg, DRM_RAS_A_ERROR_THRESHOLD_ATTRS_ERROR_ID, error_id);
> > +	if (ret)
> > +		return ret;
> > +
> > +	ret = nla_put_string(msg, DRM_RAS_A_ERROR_THRESHOLD_ATTRS_ERROR_NAME,
> > +			     error_name);
> > +	if (ret)
> > +		return ret;
> > +
> > +	return nla_put_u32(msg, DRM_RAS_A_ERROR_THRESHOLD_ATTRS_ERROR_THRESHOLD,
> > +			   value);
> > +}
> > +
> >   static int doit_reply_counter_value(struct genl_info *info, u32 node_id,
> >   				    u32 error_id)
> >   {
> > @@ -216,6 +256,42 @@ static int doit_reply_counter_value(struct genl_info *info, u32 node_id,
> >   	return genlmsg_reply(msg, info);
> >   }
> > +static int doit_reply_threshold_value(struct genl_info *info, u32 node_id,
> > +				      u32 error_id)
> > +{
> > +	struct sk_buff *msg;
> > +	struct nlattr *hdr;
> > +	const char *error_name;
> > +	u32 value;
> > +	int ret;
> > +
> > +	msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
> > +	if (!msg)
> > +		return -ENOMEM;
> > +
> > +	hdr = genlmsg_iput(msg, info);
> > +	if (!hdr) {
> > +		nlmsg_free(msg);
> > +		return -EMSGSIZE;
> > +	}
> > +
> > +	ret = get_node_error_threshold(node_id, error_id,
> > +				       &error_name, &value);
> > +	if (ret)
> > +		return ret;
> 
> You have to cancel and free genlmsg here.
> Looks like the counter patch also has the same issue. Will send out a fix.

Yeah, failed attempt at stealing your code :(

Raag

> > +	ret = msg_reply_threshold_value(msg, error_id, error_name, value);
> > +	if (ret) {
> > +		genlmsg_cancel(msg, hdr);
> > +		nlmsg_free(msg);
> > +		return ret;
> > +	}
> > +
> > +	genlmsg_end(msg, hdr);
> > +
> > +	return genlmsg_reply(msg, info);
> > +}
> > +
> >   /**
> >    * drm_ras_nl_get_error_counter_dumpit() - Dump all Error Counters
> >    * @skb: Netlink message buffer
> > @@ -314,6 +390,33 @@ int drm_ras_nl_get_error_counter_doit(struct sk_buff *skb,
> >   	return doit_reply_counter_value(info, node_id, error_id);
> >   }
> > +/**
> > + * drm_ras_nl_get_error_threshold_doit() - Query threshold value of the error
> Nit: an
> 
> Thanks
> Riana
> > + * @skb: Netlink message buffer
> > + * @info: Generic Netlink info containing attributes of the request
> > + *
> > + * Extracts the node ID and error ID from the netlink attributes and
> > + * retrieves the current threshold of the corresponding error. Sends the
> > + * result back to the requesting user via the standard Genl reply.
> > + *
> > + * Return: 0 on success, or negative errno on failure.
> > + */
> > +int drm_ras_nl_get_error_threshold_doit(struct sk_buff *skb,
> > +				      struct genl_info *info)
> > +{
> > +	u32 node_id, error_id;
> > +
> > +	if (!info->attrs ||
> > +	    GENL_REQ_ATTR_CHECK(info, DRM_RAS_A_ERROR_THRESHOLD_ATTRS_NODE_ID) ||
> > +	    GENL_REQ_ATTR_CHECK(info, DRM_RAS_A_ERROR_THRESHOLD_ATTRS_ERROR_ID))
> > +		return -EINVAL;
> > +
> > +	node_id = nla_get_u32(info->attrs[DRM_RAS_A_ERROR_THRESHOLD_ATTRS_NODE_ID]);
> > +	error_id = nla_get_u32(info->attrs[DRM_RAS_A_ERROR_THRESHOLD_ATTRS_ERROR_ID]);
> > +
> > +	return doit_reply_threshold_value(info, node_id, error_id);
> > +}
> > +
> >   /**
> >    * drm_ras_node_register() - Register a new RAS node
> >    * @node: Node structure to register
> > diff --git a/drivers/gpu/drm/drm_ras_nl.c b/drivers/gpu/drm/drm_ras_nl.c
> > index 16803d0c4a44..48e231734f4d 100644
> > --- a/drivers/gpu/drm/drm_ras_nl.c
> > +++ b/drivers/gpu/drm/drm_ras_nl.c
> > @@ -22,6 +22,12 @@ static const struct nla_policy drm_ras_get_error_counter_dump_nl_policy[DRM_RAS_
> >   	[DRM_RAS_A_ERROR_COUNTER_ATTRS_NODE_ID] = { .type = NLA_U32, },
> >   };
> > +/* DRM_RAS_CMD_GET_ERROR_THRESHOLD - do */
> > +static const struct nla_policy drm_ras_get_error_threshold_nl_policy[DRM_RAS_A_ERROR_THRESHOLD_ATTRS_ERROR_ID + 1] = {
> > +	[DRM_RAS_A_ERROR_THRESHOLD_ATTRS_NODE_ID] = { .type = NLA_U32, },
> > +	[DRM_RAS_A_ERROR_THRESHOLD_ATTRS_ERROR_ID] = { .type = NLA_U32, },
> > +};
> > +
> >   /* Ops table for drm_ras */
> >   static const struct genl_split_ops drm_ras_nl_ops[] = {
> >   	{
> > @@ -43,6 +49,13 @@ static const struct genl_split_ops drm_ras_nl_ops[] = {
> >   		.maxattr	= DRM_RAS_A_ERROR_COUNTER_ATTRS_NODE_ID,
> >   		.flags		= GENL_ADMIN_PERM | GENL_CMD_CAP_DUMP,
> >   	},
> > +	{
> > +		.cmd		= DRM_RAS_CMD_GET_ERROR_THRESHOLD,
> > +		.doit		= drm_ras_nl_get_error_threshold_doit,
> > +		.policy		= drm_ras_get_error_threshold_nl_policy,
> > +		.maxattr	= DRM_RAS_A_ERROR_THRESHOLD_ATTRS_ERROR_ID,
> > +		.flags		= GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
> > +	},
> >   };
> >   struct genl_family drm_ras_nl_family __ro_after_init = {
> > diff --git a/drivers/gpu/drm/drm_ras_nl.h b/drivers/gpu/drm/drm_ras_nl.h
> > index 06ccd9342773..540fe22e2312 100644
> > --- a/drivers/gpu/drm/drm_ras_nl.h
> > +++ b/drivers/gpu/drm/drm_ras_nl.h
> > @@ -18,6 +18,8 @@ int drm_ras_nl_get_error_counter_doit(struct sk_buff *skb,
> >   				      struct genl_info *info);
> >   int drm_ras_nl_get_error_counter_dumpit(struct sk_buff *skb,
> >   					struct netlink_callback *cb);
> > +int drm_ras_nl_get_error_threshold_doit(struct sk_buff *skb,
> > +					struct genl_info *info);
> >   extern struct genl_family drm_ras_nl_family;
> > diff --git a/include/drm/drm_ras.h b/include/drm/drm_ras.h
> > index 5d50209e51db..50cee70bd065 100644
> > --- a/include/drm/drm_ras.h
> > +++ b/include/drm/drm_ras.h
> > @@ -57,6 +57,20 @@ struct drm_ras_node {
> >   	 */
> >   	int (*query_error_counter)(struct drm_ras_node *node, u32 error_id,
> >   				   const char **name, u32 *val);
> > +	/**
> > +	 * @query_error_threshold:
> > +	 *
> > +	 * This callback is used by drm-ras to query threshold value of a
> > +	 * specific error.
> > +	 *
> > +	 * Driver should expect query_error_threshold() to be called with
> > +	 * error_id from `error_counter_range.first` to
> > +	 * `error_counter_range.last`.
> > +	 *
> > +	 * Returns: 0 on success, negative error code on failure.
> > +	 */
> > +	int (*query_error_threshold)(struct drm_ras_node *node, u32 error_id,
> > +				     const char **name, u32 *val);
> >   	/** @priv: Driver private data */
> >   	void *priv;
> > diff --git a/include/uapi/drm/drm_ras.h b/include/uapi/drm/drm_ras.h
> > index 5f40fa5b869d..49c5ca497d73 100644
> > --- a/include/uapi/drm/drm_ras.h
> > +++ b/include/uapi/drm/drm_ras.h
> > @@ -38,9 +38,20 @@ enum {
> >   	DRM_RAS_A_ERROR_COUNTER_ATTRS_MAX = (__DRM_RAS_A_ERROR_COUNTER_ATTRS_MAX - 1)
> >   };
> > +enum {
> > +	DRM_RAS_A_ERROR_THRESHOLD_ATTRS_NODE_ID = 1,
> > +	DRM_RAS_A_ERROR_THRESHOLD_ATTRS_ERROR_ID,
> > +	DRM_RAS_A_ERROR_THRESHOLD_ATTRS_ERROR_NAME,
> > +	DRM_RAS_A_ERROR_THRESHOLD_ATTRS_ERROR_THRESHOLD,
> > +
> > +	__DRM_RAS_A_ERROR_THRESHOLD_ATTRS_MAX,
> > +	DRM_RAS_A_ERROR_THRESHOLD_ATTRS_MAX = (__DRM_RAS_A_ERROR_THRESHOLD_ATTRS_MAX - 1)
> > +};
> > +
> >   enum {
> >   	DRM_RAS_CMD_LIST_NODES = 1,
> >   	DRM_RAS_CMD_GET_ERROR_COUNTER,
> > +	DRM_RAS_CMD_GET_ERROR_THRESHOLD,
> >   	__DRM_RAS_CMD_MAX,
> >   	DRM_RAS_CMD_MAX = (__DRM_RAS_CMD_MAX - 1)

^ permalink raw reply

* Re: [PATCH v1 03/11] drm/ras: Introduce set-error-threshold
From: Tauro, Riana @ 2026-04-22  6:12 UTC (permalink / raw)
  To: Raag Jadav, intel-xe, dri-devel, netdev
  Cc: simona.vetter, airlied, kuba, lijo.lazar, Hawking.Zhang, davem,
	pabeni, edumazet, maarten, zachary.mckevitt, rodrigo.vivi,
	michal.wajdeczko, matthew.d.roper, umesh.nerlige.ramappa,
	mallesh.koujalagi, soham.purkait, anoop.c.vijay,
	aravind.iddamsetty
In-Reply-To: <20260417211730.837345-4-raag.jadav@intel.com>


On 4/18/2026 2:46 AM, Raag Jadav wrote:
> Add set-error-threshold command support which allows setting threshold
> value of the error. Threshold in RAS context means the number of errors
> the hardware is expected to accumulate before it raises them to software.
> This is to have a fine grained control over error notifications that are
> raised by the hardware.
>
> Signed-off-by: Raag Jadav <raag.jadav@intel.com>
> ---
>   Documentation/gpu/drm-ras.rst            |  9 +++++
>   Documentation/netlink/specs/drm_ras.yaml | 12 ++++++
>   drivers/gpu/drm/drm_ras.c                | 48 ++++++++++++++++++++++++
>   drivers/gpu/drm/drm_ras_nl.c             | 14 +++++++
>   drivers/gpu/drm/drm_ras_nl.h             |  2 +
>   include/drm/drm_ras.h                    | 13 +++++++
>   include/uapi/drm/drm_ras.h               |  1 +
>   7 files changed, 99 insertions(+)
>
> diff --git a/Documentation/gpu/drm-ras.rst b/Documentation/gpu/drm-ras.rst
> index 6443dfd1677f..a819aa150604 100644
> --- a/Documentation/gpu/drm-ras.rst
> +++ b/Documentation/gpu/drm-ras.rst
> @@ -54,6 +54,8 @@ User space tools can:
>     ``node-id`` and ``error-id`` as parameters.
>   * Query specific error threshold value with the ``get-error-threshold`` command, using both
>     ``node-id`` and ``error-id`` as parameters.
> +* Set specific error threshold value with the ``set-error-threshold`` command, using
> +  ``node-id``, ``error-id`` and ``error-threshold`` as parameters.
>   
>   YAML-based Interface
>   --------------------
> @@ -109,3 +111,10 @@ Example: Query threshold value of a given error
>   
>       sudo ynl --family drm_ras --do get-error-threshold --json '{"node-id":0, "error-id":1}'
>       {'error-id': 1, 'error-name': 'error_name1', 'error-threshold': 0}
> +
> +Example: Set threshold value of a given error
> +
> +.. code-block:: bash
> +
> +    sudo ynl --family drm_ras --do set-error-threshold --json '{"node-id":0, "error-id":1, "error-threshold":8}'
> +    None
> diff --git a/Documentation/netlink/specs/drm_ras.yaml b/Documentation/netlink/specs/drm_ras.yaml
> index 95a939fb987d..09824309cdff 100644
> --- a/Documentation/netlink/specs/drm_ras.yaml
> +++ b/Documentation/netlink/specs/drm_ras.yaml
> @@ -150,3 +150,15 @@ operations:
>               - error-id
>               - error-name
>               - error-threshold
> +    -
> +      name: set-error-threshold
> +      doc: >-
> +           Set threshold value of the error.
> +      attribute-set: error-threshold-attrs
> +      flags: [admin-perm]
> +      do:
> +        request:
> +          attributes:
> +            - node-id
> +            - error-id
> +            - error-threshold
> diff --git a/drivers/gpu/drm/drm_ras.c b/drivers/gpu/drm/drm_ras.c
> index d2d853d5d69c..e4ff6d87f824 100644
> --- a/drivers/gpu/drm/drm_ras.c
> +++ b/drivers/gpu/drm/drm_ras.c
> @@ -41,6 +41,9 @@
>    *    Userspace must provide Node ID and Error ID.
>    *    Returns the threshold value of a specific error.
>    *
> + * 4. SET_ERROR_THRESHOLD: Set threshold value of the error.
> + *    Userspace must provide Node ID, Error ID and Threshold value to be set.
> + *
>    * Node registration:
>    *
>    * - drm_ras_node_register(): Registers a new node and assigns
> @@ -72,6 +75,8 @@
>    *   operation, fetching a counter value from a specific node.
>    * - drm_ras_nl_get_error_threshold_doit(): Implements the GET_ERROR_THRESHOLD doit
>    *   operation, fetching the threshold value of a specific error.
> + * - drm_ras_nl_set_error_threshold_doit(): Implements the SET_ERROR_THRESHOLD doit
> + *   operation, setting the threshold value of a specific error.
>    */
>   
>   static DEFINE_XARRAY_ALLOC(drm_ras_xa);
> @@ -184,6 +189,21 @@ static int get_node_error_threshold(u32 node_id, u32 error_id,
>   	return node->query_error_threshold(node, error_id, name, value);
>   }
>   
> +static int set_node_error_threshold(u32 node_id, u32 error_id, u32 value)
> +{
> +	struct drm_ras_node *node;
> +
> +	node = xa_load(&drm_ras_xa, node_id);
> +	if (!node || !node->set_error_threshold)
> +		return -ENOENT;

Use -EOPNOTSUPP for absence of function

> +
> +	if (error_id < node->error_counter_range.first ||
> +	    error_id > node->error_counter_range.last)
> +		return -EINVAL;
> +
> +	return node->set_error_threshold(node, error_id, value);
> +}
> +
>   static int msg_reply_counter_value(struct sk_buff *msg, u32 error_id,
>   				   const char *error_name, u32 value)
>   {
> @@ -417,6 +437,34 @@ int drm_ras_nl_get_error_threshold_doit(struct sk_buff *skb,
>   	return doit_reply_threshold_value(info, node_id, error_id);
>   }
>   
> +/**
> + * drm_ras_nl_set_error_threshold_doit() - Set threshold value of the error
> + * @skb: Netlink message buffer
> + * @info: Generic Netlink info containing attributes of the request
> + *
> + * Extracts the node ID, error ID and threshold value from the netlink attributes
> + * and sets the threshold of the corresponding error.
> + *
> + * Return: 0 on success, or negative errno on failure.
> + */
> +int drm_ras_nl_set_error_threshold_doit(struct sk_buff *skb,
> +				      struct genl_info *info)
> +{
> +	u32 node_id, error_id, value;
> +
> +	if (!info->attrs ||
> +	    GENL_REQ_ATTR_CHECK(info, DRM_RAS_A_ERROR_THRESHOLD_ATTRS_NODE_ID) ||
> +	    GENL_REQ_ATTR_CHECK(info, DRM_RAS_A_ERROR_THRESHOLD_ATTRS_ERROR_ID) ||
> +	    GENL_REQ_ATTR_CHECK(info, DRM_RAS_A_ERROR_THRESHOLD_ATTRS_ERROR_THRESHOLD))
> +		return -EINVAL;
> +
> +	node_id = nla_get_u32(info->attrs[DRM_RAS_A_ERROR_THRESHOLD_ATTRS_NODE_ID]);
> +	error_id = nla_get_u32(info->attrs[DRM_RAS_A_ERROR_THRESHOLD_ATTRS_ERROR_ID]);
> +	value = nla_get_u32(info->attrs[DRM_RAS_A_ERROR_THRESHOLD_ATTRS_ERROR_THRESHOLD]);

do we need a check for max threshold here? Probably configured by drivers?
Or is it upto the driver to check? If its upto the driver, please add it 
in the document

Thanks
Riana

> +
> +	return set_node_error_threshold(node_id, error_id, value);
> +}
> +
>   /**
>    * drm_ras_node_register() - Register a new RAS node
>    * @node: Node structure to register
> diff --git a/drivers/gpu/drm/drm_ras_nl.c b/drivers/gpu/drm/drm_ras_nl.c
> index 48e231734f4d..8b202d773dac 100644
> --- a/drivers/gpu/drm/drm_ras_nl.c
> +++ b/drivers/gpu/drm/drm_ras_nl.c
> @@ -28,6 +28,13 @@ static const struct nla_policy drm_ras_get_error_threshold_nl_policy[DRM_RAS_A_E
>   	[DRM_RAS_A_ERROR_THRESHOLD_ATTRS_ERROR_ID] = { .type = NLA_U32, },
>   };
>   
> +/* DRM_RAS_CMD_SET_ERROR_THRESHOLD - do */
> +static const struct nla_policy drm_ras_set_error_threshold_nl_policy[DRM_RAS_A_ERROR_THRESHOLD_ATTRS_ERROR_THRESHOLD + 1] = {
> +	[DRM_RAS_A_ERROR_THRESHOLD_ATTRS_NODE_ID] = { .type = NLA_U32, },
> +	[DRM_RAS_A_ERROR_THRESHOLD_ATTRS_ERROR_ID] = { .type = NLA_U32, },
> +	[DRM_RAS_A_ERROR_THRESHOLD_ATTRS_ERROR_THRESHOLD] = { .type = NLA_U32, },
> +};
> +
>   /* Ops table for drm_ras */
>   static const struct genl_split_ops drm_ras_nl_ops[] = {
>   	{
> @@ -56,6 +63,13 @@ static const struct genl_split_ops drm_ras_nl_ops[] = {
>   		.maxattr	= DRM_RAS_A_ERROR_THRESHOLD_ATTRS_ERROR_ID,
>   		.flags		= GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
>   	},
> +	{
> +		.cmd		= DRM_RAS_CMD_SET_ERROR_THRESHOLD,
> +		.doit		= drm_ras_nl_set_error_threshold_doit,
> +		.policy		= drm_ras_set_error_threshold_nl_policy,
> +		.maxattr	= DRM_RAS_A_ERROR_THRESHOLD_ATTRS_ERROR_THRESHOLD,
> +		.flags		= GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
> +	},
>   };
>   
>   struct genl_family drm_ras_nl_family __ro_after_init = {
> diff --git a/drivers/gpu/drm/drm_ras_nl.h b/drivers/gpu/drm/drm_ras_nl.h
> index 540fe22e2312..9db7f5d00201 100644
> --- a/drivers/gpu/drm/drm_ras_nl.h
> +++ b/drivers/gpu/drm/drm_ras_nl.h
> @@ -20,6 +20,8 @@ int drm_ras_nl_get_error_counter_dumpit(struct sk_buff *skb,
>   					struct netlink_callback *cb);
>   int drm_ras_nl_get_error_threshold_doit(struct sk_buff *skb,
>   					struct genl_info *info);
> +int drm_ras_nl_set_error_threshold_doit(struct sk_buff *skb,
> +					struct genl_info *info);
>   
>   extern struct genl_family drm_ras_nl_family;
>   
> diff --git a/include/drm/drm_ras.h b/include/drm/drm_ras.h
> index 50cee70bd065..7a69821b8b78 100644
> --- a/include/drm/drm_ras.h
> +++ b/include/drm/drm_ras.h
> @@ -71,6 +71,19 @@ struct drm_ras_node {
>   	 */
>   	int (*query_error_threshold)(struct drm_ras_node *node, u32 error_id,
>   				     const char **name, u32 *val);
> +	/**
> +	 * @set_error_threshold:
> +	 *
> +	 * This callback is used by drm-ras to set threshold value of a specific
> +	 * error.
> +	 *
> +	 * Driver should expect set_error_threshold() to be called with error_id
> +	 * from `error_counter_range.first` to `error_counter_range.last`.
> +	 *
> +	 * Returns: 0 on success, negative error code on failure.
> +	 */
> +	int (*set_error_threshold)(struct drm_ras_node *node, u32 error_id,
> +				   u32 val);
>   
>   	/** @priv: Driver private data */
>   	void *priv;
> diff --git a/include/uapi/drm/drm_ras.h b/include/uapi/drm/drm_ras.h
> index 49c5ca497d73..8ff0311d0d63 100644
> --- a/include/uapi/drm/drm_ras.h
> +++ b/include/uapi/drm/drm_ras.h
> @@ -52,6 +52,7 @@ enum {
>   	DRM_RAS_CMD_LIST_NODES = 1,
>   	DRM_RAS_CMD_GET_ERROR_COUNTER,
>   	DRM_RAS_CMD_GET_ERROR_THRESHOLD,
> +	DRM_RAS_CMD_SET_ERROR_THRESHOLD,
>   
>   	__DRM_RAS_CMD_MAX,
>   	DRM_RAS_CMD_MAX = (__DRM_RAS_CMD_MAX - 1)

^ permalink raw reply

* Re: [net-next PATCH 09/10] net: dsa: realtek: rtl8365mb: add bridge port flags
From: Luiz Angelo Daros de Luca @ 2026-04-22  6:06 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Andrew Lunn, Vladimir Oltean, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Simon Horman, Alvin Šipraga,
	Yury Norov, Rasmus Villemoes, Russell King, netdev, linux-kernel
In-Reply-To: <CAD++jL=v6qe+dVF-wk3cPg3aw8Qp7pS6BVtAqmWURJ=JvMvDHA@mail.gmail.com>

> > +static int rtl8365mb_port_set_ucast_flood(struct realtek_priv *priv, int port,
> > +                                         bool enable)
> > +static int rtl8365mb_port_set_mcast_flood(struct realtek_priv *priv, int port,
> > +                                         bool enable)
> > +static int rtl8365mb_port_set_bcast_flood(struct realtek_priv *priv, int port,
> > +                                         bool enable)
>
> Those are small and just writing registers so I guess they can be kept local,
> but I think they should be accessed indirectly through
> struct realtek_ops .rtl8366_port_set_ucast_flood() etc.

Sure.

> > +static int rtl8365mb_port_bridge_flags(struct dsa_switch *ds, int port,
> > +                                      struct switchdev_brport_flags flags,
> > +                                      struct netlink_ext_ack *exack)
>
> Move this one to rtl8366-core.c under the name rtl8366_port_[pre_]bridge_flags()
> and use the abstract accessors to do the register writes.

OK

> > @@ -1691,6 +1797,8 @@ static int rtl8365mb_port_bridge_join(struct dsa_switch *ds, int port,
> >         int ret;
> >         int i;
> >
> > +       dev_dbg(priv->dev, "bridge %d join port %d\n", port, bridge.num);
> > +
> >         /* Add this port to the isolation group of every other port
> >          * offloading this bridge.
> >          */
> > @@ -1730,6 +1838,8 @@ static void rtl8365mb_port_bridge_leave(struct dsa_switch *ds, int port,
> >         u32 mask = 0;
> >         int i;
> >
> > +       dev_dbg(priv->dev, "bridge %d leave port %d\n", port, bridge.num);
> > +
> >         /* Remove this port from the isolation group of every other
> >          * port offloading this bridge.
> >          */
>
> These debug prints seem unrelated to this patch?

Yes, sorry. I'll move them.

>
> > @@ -2547,6 +2657,19 @@ static int rtl8365mb_setup(struct dsa_switch *ds)
> >                 if (ret)
> >                         goto out_teardown_irq;
> >
> > +               /* Enable all types of flooding */
> > +               ret = rtl8365mb_port_set_ucast_flood(priv, i, true);
> > +               if (ret)
> > +                       goto out_teardown_irq;
> > +
> > +               ret = rtl8365mb_port_set_mcast_flood(priv, i, true);
> > +               if (ret)
> > +                       goto out_teardown_irq;
> > +
> > +               ret = rtl8365mb_port_set_bcast_flood(priv, i, true);
> > +               if (ret)
> > +                       goto out_teardown_irq;
>
> Create rtl8366_setup_flood_control() in realtek-core.c and add these
> three calls as a helper using the rtl8366_* generic calls there. It will be
> done the same on all chips.

OK. I think

rtl83xx_setup_port_flood_control(struct realtek_priv *priv, int port);

might be better as we can avoid looping again over the ports.

Regards,

Luiz

^ permalink raw reply

* Re: [PATCH net v1] vhost_net: fix sleeping with preempt-disabled in vhost_net_busy_poll()
From: Michael S. Tsirkin @ 2026-04-22  6:05 UTC (permalink / raw)
  To: Kohei Enju
  Cc: Jason Wang, Eugenio Pérez, kvm, virtualization, netdev,
	syzbot+6985cb8e543ea90ba8ee
In-Reply-To: <20260422023026.81960-1-kohei@enjuk.jp>

On Wed, Apr 22, 2026 at 02:30:24AM +0000, Kohei Enju wrote:
> syzbot reported "sleeping function called from invalid context" in
> vhost_net_busy_poll().
> 
> Commit 030881372460 ("vhost_net: basic polling support") introduced a
> busy-poll loop and preempt_{disable,enable}() around it, where each
> iteration calls a sleepable function inside the loop.
> 
> The purpose of disabling preemption was to keep local_clock()-based
> timeout accounting on a single CPU, rather than as a requirement of
> busy-poll itself:
> 
> https://lore.kernel.org/netdev/1448435489-5949-4-git-send-email-jasowang@redhat.com/T/#u
> 
>   Changes from RFC V1:
>   ...
>   - Disable preemption during busy looping to make sure local_clock()
>     was correctly used.
> 
> >From this perspective, migrate_disable() is sufficient here, so replace
> preempt_disable() with migrate_disable(), avoiding sleepable accesses
> from a preempt-disabled context.
> 
> Fixes: 030881372460 ("vhost_net: basic polling support")
> Tested-by: syzbot+6985cb8e543ea90ba8ee@syzkaller.appspotmail.com
> Reported-by: syzbot+6985cb8e543ea90ba8ee@syzkaller.appspotmail.com
> Closes: https://lore.kernel.org/all/69e6a414.050a0220.24bfd3.002d.GAE@google.com/T/
> Signed-off-by: Kohei Enju <kohei@enjuk.jp>

Acked-by: Michael S. Tsirkin <mst@redhat.com>

> ---
>  drivers/vhost/net.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
> index 80965181920c..c6536cad9c4f 100644
> --- a/drivers/vhost/net.c
> +++ b/drivers/vhost/net.c
> @@ -560,7 +560,7 @@ static void vhost_net_busy_poll(struct vhost_net *net,
>  	busyloop_timeout = poll_rx ? rvq->busyloop_timeout:
>  				     tvq->busyloop_timeout;
>  
> -	preempt_disable();
> +	migrate_disable();
>  	endtime = busy_clock() + busyloop_timeout;
>  
>  	while (vhost_can_busy_poll(endtime)) {
> @@ -577,7 +577,7 @@ static void vhost_net_busy_poll(struct vhost_net *net,
>  		cpu_relax();
>  	}
>  
> -	preempt_enable();
> +	migrate_enable();
>  
>  	if (poll_rx || sock_has_rx_data(sock))
>  		vhost_net_busy_poll_try_queue(net, vq);
> -- 
> 2.51.0


^ permalink raw reply

* Re: [PATCH v1 05/11] drm/xe/sysctrl: Add system controller interrupt handler
From: Tauro, Riana @ 2026-04-22  5:55 UTC (permalink / raw)
  To: Raag Jadav, intel-xe, dri-devel, netdev
  Cc: simona.vetter, airlied, kuba, lijo.lazar, Hawking.Zhang, davem,
	pabeni, edumazet, maarten, zachary.mckevitt, rodrigo.vivi,
	michal.wajdeczko, matthew.d.roper, umesh.nerlige.ramappa,
	mallesh.koujalagi, soham.purkait, anoop.c.vijay,
	aravind.iddamsetty
In-Reply-To: <20260417211730.837345-6-raag.jadav@intel.com>


On 4/18/2026 2:46 AM, Raag Jadav wrote:
> Add system controller interrupt handler which is denoted by 11th bit in
> GFX master interrupt register. While at it, add worker for scheduling
> system controller work.

Why do we need this series in the threshold patch. From what i see, we 
need only structures
Can't we only redefine those here?

I know you will have to rebase again once any patch is merged. But this 
is unnecessary noise
for the drm patch.

Thanks
Riana

>
> Co-developed-by: Soham Purkait <soham.purkait@intel.com>
> Signed-off-by: Soham Purkait <soham.purkait@intel.com>
> Signed-off-by: Raag Jadav <raag.jadav@intel.com>
> Reviewed-by: Mallesh Koujalagi <mallesh.koujalagi@intel.com>
> Reviewed-by: Riana Tauro <riana.tauro@intel.com>
> ---
>   drivers/gpu/drm/xe/regs/xe_irq_regs.h |  1 +
>   drivers/gpu/drm/xe/xe_irq.c           |  2 ++
>   drivers/gpu/drm/xe/xe_sysctrl.c       | 35 +++++++++++++++++++++------
>   drivers/gpu/drm/xe/xe_sysctrl.h       |  1 +
>   drivers/gpu/drm/xe/xe_sysctrl_types.h |  4 +++
>   5 files changed, 36 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/gpu/drm/xe/regs/xe_irq_regs.h b/drivers/gpu/drm/xe/regs/xe_irq_regs.h
> index 9d74f454d3ff..1d6b976c4de0 100644
> --- a/drivers/gpu/drm/xe/regs/xe_irq_regs.h
> +++ b/drivers/gpu/drm/xe/regs/xe_irq_regs.h
> @@ -22,6 +22,7 @@
>   #define   DISPLAY_IRQ				REG_BIT(16)
>   #define   SOC_H2DMEMINT_IRQ			REG_BIT(13)
>   #define   I2C_IRQ				REG_BIT(12)
> +#define   SYSCTRL_IRQ				REG_BIT(11)
>   #define   GT_DW_IRQ(x)				REG_BIT(x)
>   
>   /*
> diff --git a/drivers/gpu/drm/xe/xe_irq.c b/drivers/gpu/drm/xe/xe_irq.c
> index 9a775c6588dc..e9f0b3cad06d 100644
> --- a/drivers/gpu/drm/xe/xe_irq.c
> +++ b/drivers/gpu/drm/xe/xe_irq.c
> @@ -24,6 +24,7 @@
>   #include "xe_mmio.h"
>   #include "xe_pxp.h"
>   #include "xe_sriov.h"
> +#include "xe_sysctrl.h"
>   #include "xe_tile.h"
>   
>   /*
> @@ -525,6 +526,7 @@ static irqreturn_t dg1_irq_handler(int irq, void *arg)
>   				xe_heci_csc_irq_handler(xe, master_ctl);
>   			xe_display_irq_handler(xe, master_ctl);
>   			xe_i2c_irq_handler(xe, master_ctl);
> +			xe_sysctrl_irq_handler(xe, master_ctl);
>   			xe_mert_irq_handler(xe, master_ctl);
>   			gu_misc_iir = gu_misc_irq_ack(xe, master_ctl);
>   		}
> diff --git a/drivers/gpu/drm/xe/xe_sysctrl.c b/drivers/gpu/drm/xe/xe_sysctrl.c
> index 2bcef304eb9a..7de3e73bd8e0 100644
> --- a/drivers/gpu/drm/xe/xe_sysctrl.c
> +++ b/drivers/gpu/drm/xe/xe_sysctrl.c
> @@ -8,6 +8,7 @@
>   
>   #include <drm/drm_managed.h>
>   
> +#include "regs/xe_irq_regs.h"
>   #include "regs/xe_sysctrl_regs.h"
>   #include "xe_device.h"
>   #include "xe_mmio.h"
> @@ -30,10 +31,16 @@
>   static void sysctrl_fini(void *arg)
>   {
>   	struct xe_device *xe = arg;
> +	struct xe_sysctrl *sc = &xe->sc;
>   
> +	disable_work_sync(&sc->work);
>   	xe->soc_remapper.set_sysctrl_region(xe, 0);
>   }
>   
> +static void xe_sysctrl_work(struct work_struct *work)
> +{
> +}
> +
>   /**
>    * xe_sysctrl_init() - Initialize System Controller subsystem
>    * @xe: xe device instance
> @@ -55,12 +62,6 @@ int xe_sysctrl_init(struct xe_device *xe)
>   	if (!xe->info.has_sysctrl)
>   		return 0;
>   
> -	xe->soc_remapper.set_sysctrl_region(xe, SYSCTRL_MAILBOX_INDEX);
> -
> -	ret = devm_add_action_or_reset(xe->drm.dev, sysctrl_fini, xe);
> -	if (ret)
> -		return ret;
> -
>   	sc->mmio = devm_kzalloc(xe->drm.dev, sizeof(*sc->mmio), GFP_KERNEL);
>   	if (!sc->mmio)
>   		return -ENOMEM;
> @@ -73,9 +74,29 @@ int xe_sysctrl_init(struct xe_device *xe)
>   	if (ret)
>   		return ret;
>   
> +	xe->soc_remapper.set_sysctrl_region(xe, SYSCTRL_MAILBOX_INDEX);
>   	xe_sysctrl_mailbox_init(sc);
> +	INIT_WORK(&sc->work, xe_sysctrl_work);
>   
> -	return 0;
> +	return devm_add_action_or_reset(xe->drm.dev, sysctrl_fini, xe);
> +}
> +
> +/**
> + * xe_sysctrl_irq_handler() - Handler for System Controller interrupts
> + * @xe: xe device instance
> + * @master_ctl: interrupt register
> + *
> + * Handle interrupts generated by System Controller.
> + */
> +void xe_sysctrl_irq_handler(struct xe_device *xe, u32 master_ctl)
> +{
> +	struct xe_sysctrl *sc = &xe->sc;
> +
> +	if (!xe->info.has_sysctrl || !sc->work.func)
> +		return;
> +
> +	if (master_ctl & SYSCTRL_IRQ)
> +		schedule_work(&sc->work);
>   }
>   
>   /**
> diff --git a/drivers/gpu/drm/xe/xe_sysctrl.h b/drivers/gpu/drm/xe/xe_sysctrl.h
> index f3b0f3716b2f..f7469bfc9324 100644
> --- a/drivers/gpu/drm/xe/xe_sysctrl.h
> +++ b/drivers/gpu/drm/xe/xe_sysctrl.h
> @@ -17,6 +17,7 @@ static inline struct xe_device *sc_to_xe(struct xe_sysctrl *sc)
>   }
>   
>   int xe_sysctrl_init(struct xe_device *xe);
> +void xe_sysctrl_irq_handler(struct xe_device *xe, u32 master_ctl);
>   void xe_sysctrl_pm_resume(struct xe_device *xe);
>   
>   #endif
> diff --git a/drivers/gpu/drm/xe/xe_sysctrl_types.h b/drivers/gpu/drm/xe/xe_sysctrl_types.h
> index 8217f6befe70..5f408d6491ef 100644
> --- a/drivers/gpu/drm/xe/xe_sysctrl_types.h
> +++ b/drivers/gpu/drm/xe/xe_sysctrl_types.h
> @@ -8,6 +8,7 @@
>   
>   #include <linux/mutex.h>
>   #include <linux/types.h>
> +#include <linux/workqueue_types.h>
>   
>   struct xe_mmio;
>   
> @@ -27,6 +28,9 @@ struct xe_sysctrl {
>   
>   	/** @phase_bit: Message boundary phase toggle bit (0 or 1) */
>   	bool phase_bit;
> +
> +	/** @work: Pending events worker */
> +	struct work_struct work;
>   };
>   
>   #endif

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox