Netdev List
 help / color / mirror / Atom feed
* Re: [syzbot] [kvm?] [net?] [virt?] BUG: sleeping function called from invalid context in vhost_get_avail_idx
From: Kohei Enju @ 2026-04-21 17:11 UTC (permalink / raw)
  To: syzbot; +Cc: jasowang, linux-kernel, mst, netdev, syzkaller-bugs
In-Reply-To: <69e6a414.050a0220.24bfd3.002d.GAE@google.com>

On 04/20 15:09, syzbot wrote:
> Hello,
> 
> syzbot found the following issue on:
> 
> HEAD commit:    8541d8f725c6 Merge tag 'mtd/for-7.1' of git://git.kernel.o..
> git tree:       upstream
> console output: https://syzkaller.appspot.com/x/log.txt?x=136454ce580000
> kernel config:  https://syzkaller.appspot.com/x/.config?x=7e54da1916e8d11f
> dashboard link: https://syzkaller.appspot.com/bug?extid=6985cb8e543ea90ba8ee
> compiler:       gcc (Debian 14.2.0-19) 14.2.0, GNU ld (GNU Binutils for Debian) 2.44
> syz repro:      https://syzkaller.appspot.com/x/repro.syz?x=15d264ce580000
> C reproducer:   https://syzkaller.appspot.com/x/repro.c?x=143ec1ba580000
> 
> Downloadable assets:
> disk image (non-bootable): https://storage.googleapis.com/syzbot-assets/d900f083ada3/non_bootable_disk-8541d8f7.raw.xz
> vmlinux: https://storage.googleapis.com/syzbot-assets/22dfea2c37c2/vmlinux-8541d8f7.xz
> kernel image: https://storage.googleapis.com/syzbot-assets/e2f93ad68fe3/bzImage-8541d8f7.xz
> 
> IMPORTANT: if you fix the issue, please add the following tag to the commit:
> Reported-by: syzbot+6985cb8e543ea90ba8ee@syzkaller.appspotmail.com
> 
> BUG: sleeping function called from invalid context at drivers/vhost/vhost.c:1527
> in_atomic(): 1, irqs_disabled(): 0, non_block: 0, pid: 6110, name: vhost-6109
> preempt_count: 1, expected: 0
> RCU nest depth: 0, expected: 0
> 2 locks held by vhost-6109/6110:
>  #0: ffff888055624cb0 (&vq->mutex/1){+.+.}-{4:4}, at: handle_tx+0x2d/0x160 drivers/vhost/net.c:971
>  #1: ffff888055620248 (&vq->mutex){+.+.}-{4:4}, at: vhost_net_busy_poll+0x9c/0x730 drivers/vhost/net.c:554
> Preemption disabled at:
> [<ffffffff88f1a006>] vhost_net_busy_poll+0x1c6/0x730 drivers/vhost/net.c:563

I think the blamed commit may be commit 030881372460 ("vhost_net: basic
polling support"), since it introduced preempt_{disable,enable}() around
the busy-poll loop, which calls a sleepable function inside the loop.

Also, from the changelog of the series,

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.

So my understanding is that preempt_disable() was introduced to keep
local_clock() based timeout accounting on a single CPU, rather than as a
requirement of busy polling itself.

If my understanding is correct, migrate_disable() is sufficient here
instead of preempt_disable(), avoiding sleepable accesses from a
preempt-disabled context.

#syz test

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);


> CPU: 0 UID: 0 PID: 6110 Comm: vhost-6109 Not tainted syzkaller #0 PREEMPT(full) 
> Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
> Call Trace:
>  <TASK>
>  __dump_stack lib/dump_stack.c:94 [inline]
>  dump_stack_lvl+0x100/0x190 lib/dump_stack.c:120
>  __might_resched.cold+0x1ec/0x232 kernel/sched/core.c:9162
>  __might_fault+0x8b/0x140 mm/memory.c:7322
>  vhost_get_avail_idx+0x31c/0x4f0 drivers/vhost/vhost.c:1527
>  vhost_vq_avail_empty drivers/vhost/vhost.c:3206 [inline]
>  vhost_vq_avail_empty+0xa9/0xe0 drivers/vhost/vhost.c:3199
>  vhost_net_busy_poll+0x297/0x730 drivers/vhost/net.c:574
>  vhost_net_tx_get_vq_desc drivers/vhost/net.c:610 [inline]
>  get_tx_bufs.constprop.0+0x338/0x600 drivers/vhost/net.c:650
>  handle_tx_copy+0x28c/0x12e0 drivers/vhost/net.c:778
>  handle_tx+0x139/0x160 drivers/vhost/net.c:985
>  vhost_run_work_list+0x183/0x220 drivers/vhost/vhost.c:454
>  vhost_task_fn+0x156/0x430 kernel/vhost_task.c:49
>  ret_from_fork+0x72b/0xd50 arch/x86/kernel/process.c:158
>  ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
>  </TASK>
> 
> 
> ---
> This report is generated by a bot. It may contain errors.
> See https://goo.gl/tpsmEJ for more information about syzbot.
> syzbot engineers can be reached at syzkaller@googlegroups.com.
> 
> syzbot will keep track of this issue. See:
> https://goo.gl/tpsmEJ#status for how to communicate with syzbot.
> 
> If the report is already addressed, let syzbot know by replying with:
> #syz fix: exact-commit-title
> 
> If you want syzbot to run the reproducer, reply with:
> #syz test: git://repo/address.git branch-or-commit-hash
> If you attach or paste a git patch, syzbot will apply it before testing.
> 
> If you want to overwrite report's subsystems, reply with:
> #syz set subsystems: new-subsystem
> (See the list of subsystem names on the web dashboard)
> 
> If the report is a duplicate of another one, reply with:
> #syz dup: exact-subject-of-another-report
> 
> If you want to undo deduplication, reply with:
> #syz undup

^ permalink raw reply related

* Re: [PATCH net-deletions] net: remove ISDN subsystem and Bluetooth CMTP
From: Randy Dunlap @ 2026-04-21 17:12 UTC (permalink / raw)
  To: Luiz Augusto von Dentz, Jakub Kicinski
  Cc: davem, netdev, edumazet, pabeni, andrew+netdev, horms, corbet,
	skhan, marcel, mchehab+huawei, jani.nikula, gregkh, demarchi,
	justonli, ivecera, jonathan.cameron, kees, marco.crivellari,
	ferr.lambarginio, nihaal, mingo, tglx, linmq006, linux-doc,
	linux-bluetooth
In-Reply-To: <CABBYNZ+yCH2hxbS32o6eDT7BDMLZd3YpjUZ=sfiw=z9XjMT6OQ@mail.gmail.com>



On 4/21/26 6:55 AM, Luiz Augusto von Dentz wrote:
> Hi Jakub,
> 
> On Mon, Apr 20, 2026 at 10:21 PM Jakub Kicinski <kuba@kernel.org> wrote:
>>
>> Remove the ISDN (mISDN, CAPI) subsystem and Bluetooth CMTP protocol
>> from the kernel tree.
>>
>>
> 
> Acked-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

Please don't send 1.7 MB emails for an Ack.

See https://people.kernel.org/tglx/,
especially "Trim replies".

-- 
~Randy


^ permalink raw reply

* Re: [PATCH net-deletions] net: remove ax25 and amateur radio (hamradio) subsystem
From: Stephen Hemminger @ 2026-04-21 17:14 UTC (permalink / raw)
  To: Dan Cross
  Cc: Jakub Kicinski, davem, netdev, edumazet, pabeni, andrew+netdev,
	horms, corbet, skhan, federico.vaga, carlos.bilbao, avadhut.naik,
	alexs, si.yanteng, dzm91, 2023002089, tsbogend, dsahern,
	jani.nikula, mchehab+huawei, gregkh, jirislaby, tytso, herbert,
	ebiggers, johannes.berg, geert, pablo, tglx, mashiro.chen, mingo,
	dqfext, jreuter, sdf, pkshih, enelsonmoore, mkl, toke, kees,
	jlayton, wangliang74, aha310510, takamitz, kuniyu, linux-doc,
	linux-mips
In-Reply-To: <CAEoi9W6ZRw6aEh62Xbgkg-TW8URHbVp6dHTT9krFiTkotjTuTA@mail.gmail.com>

On Tue, 21 Apr 2026 12:17:23 -0400
Dan Cross <crossd@gmail.com> wrote:

> On Tue, Apr 21, 2026 at 9:55 AM Stephen Hemminger
> <stephen@networkplumber.org> wrote:
> > On Mon, 20 Apr 2026 19:18:23 -0700
> > Jakub Kicinski <kuba@kernel.org> wrote:  
> > > Remove the amateur radio (AX.25, NET/ROM, ROSE) protocol implementation
> > > and all associated hamradio device drivers from the kernel tree.
> > > This set of protocols has long been a huge bug/syzbot magnet,
> > > and since nobody stepped up to help us deal with the influx
> > > of the AI-generated bug reports we need to move it out of tree
> > > to protect our sanity.
> > >
> > > The code is moved to an out-of-tree repo:
> > > https://github.com/linux-netdev/mod-orphan
> > > if it's cleaned up and reworked there we can accept it back.  
> >
> > It would be good if these protocols could be done in userspace
> > or with BPF?  
> 
> Consensus for a userspace implementation is what folks on linux-hams
> seem to be converging on.
> 
> The amateur radio protocols are more or less specific to low-speed
> links, they are not particularly coupled to anything else that
> requires running in the kernel, and the main coupling point (IP over
> AX.25) can be implemented via TAP/TUN.
> 
> There are several popular packages that already implement AX.25 and
> NET/ROM in user-space (for the interested, LinBPQ seems to be the
> canonical example).  The main missing piece is ROSE, but it is likely
> easier to add that to an existing package, or potentially something
> brand new, than keep it in the kernel.
> 
> There's no compelling reason to keep these protocols in the kernel,
> whether in-tree or out-of-tree; at least, one has not been
> articulated.
> 
>         - Dan C.

Thanks, my other concern is carrying support for these in ip commands.
If not kernel based, then iproute2 doesn't need to worry.

^ permalink raw reply

* Re: [PATCH net v4 2/2] net: airoha: Add missing bits in airoha_qdma_cleanup_tx_queue()
From: Lorenzo Bianconi @ 2026-04-21 17:15 UTC (permalink / raw)
  To: Paolo Abeni
  Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Simon Horman, linux-arm-kernel, linux-mediatek, netdev
In-Reply-To: <210f5d0b-6232-4c0f-adff-3a97d54159b3@redhat.com>

[-- Attachment #1: Type: text/plain, Size: 1904 bytes --]

> On 4/17/26 8:36 AM, Lorenzo Bianconi wrote:
> > @@ -1055,8 +1058,33 @@ static void airoha_qdma_cleanup_tx_queue(struct airoha_queue *q)
> >  		e->dma_addr = 0;
> >  		e->skb = NULL;
> >  		list_add_tail(&e->list, &q->tx_list);
> > +
> > +		/* Reset DMA descriptor */
> > +		WRITE_ONCE(desc->ctrl, 0);
> > +		WRITE_ONCE(desc->addr, 0);
> > +		WRITE_ONCE(desc->data, 0);
> > +		WRITE_ONCE(desc->msg0, 0);
> > +		WRITE_ONCE(desc->msg1, 0);
> > +		WRITE_ONCE(desc->msg2, 0);
> 
> Sashiko has some complains on this patch that look legit to me.
> 
> Also the pre-existing issues mentioned WRT patch 1/2 makes such patch
> IMHO almost ineffective, I think you should address them in the same series.
> 
> Note that you should have commented on sashiko review on the ML, it
> would have saved a significant amount of time on us.

Since this series is marked as 'Changes Requested', it is not clear to me what
next steps are. I guess we have two possible approach here:

1) - Post patch 1/2 ("net: airoha: Move ndesc initialization at
     end of airoha_qdma_init_tx()") with the series available upstream
     (not merged yet) in [0] where I am fixing similar issues for
     airoha_qdma_init_rx_queue() and airoha_qdma_tx_irq_init().
   - Post patch 2/2 ("net: airoha: Add missing bits in
     airoha_qdma_cleanup_tx_queue()") with a fix for airoha_ndo_stop() waiting
     for TX/RX DMA engine to complete before running
     airoha_qdma_cleanup_tx_queue().

2) - Since all the issues rised by Sashiko are not strictly related to this
     series and they are already fixed in pending patches, just apply the fixes
     separately without the needs to repost this series.

Which approach do you prefer?

Regards,
Lorenzo

[0] https://patchwork.kernel.org/project/netdevbpf/cover/20260420-airoha_qdma_init_rx_queue-fix-v2-0-d99347e5c18d@kernel.org/

> 
> /P
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply

* Re: [PATCH 0/3] mptcp: add RECVERR and MSG_ERRQUEUE support
From: David CARLIER @ 2026-04-21 17:16 UTC (permalink / raw)
  To: Matthieu Baerts
  Cc: netdev, mptcp, martineau, geliang, davem, edumazet, kuba, pabeni,
	horms
In-Reply-To: <e190409c-3dee-4de8-b1a0-7867213cb801@kernel.org>

Thanks for the head-up, cheers !

On Tue, 21 Apr 2026 at 17:07, Matthieu Baerts <matttbe@kernel.org> wrote:
>
> Hi David,
>
> On 21/04/2026 17:22, David Carlier wrote:
> > MPTCP already advertises IP_RECVERR/IPV6_RECVERR as supported, but the
> > parent socket does not currently provide usable MSG_ERRQUEUE handling.
> >
> > This series wires the MPTCP socket up to the IPv4/IPv6 error queue
> > paths. It propagates RECVERR-related sockopts to existing and future
> > subflows, makes poll() report pending errqueue activity through the
> > parent socket, and allows recvmsg(MSG_ERRQUEUE) on the MPTCP socket to
> > consume queued errors with the parent socket ABI.
> >
> > The series also handles mixed-family subflows by applying the matching
> > sockopt according to each subflow family, and avoids silently losing an
> > error skb if requeueing to the parent socket fails under rmem pressure.
> Thank you for this series!
>
> Even if I agree it would be good to have full MSG_ERRQUEUE support,
> net-next is currently closed, and only bug fixes are accepted, see:
>
>   https://docs.kernel.org/process/maintainer-netdev.html
>
> pw-bot: defer
>
> Instead, I suggest switching the discussions only to the MPTCP ML if
> that's OK. If the CI is happy, someone will try to review it over there,
> when time permits. If not, please send the new versions only to the
> MPTCP ML, with the 'PATCH mptcp-next' prefix, and ideally on top of the
> 'export' (or 'for-review') branch of our tree. For more details:
>
>   https://www.mptcp.dev/contributing.html#kernel-development
>
> Cheers,
> Matt
> --
> Sponsored by the NGI0 Core fund.
>

^ permalink raw reply

* Re: [PATCH 18/23] cpu/hotplug: Add a new cpuhp_offline_cb() API
From: Waiman Long @ 2026-04-21 17:29 UTC (permalink / raw)
  To: Thomas Gleixner, 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,
	Chen Ridong, 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: <87o6jcb84w.ffs@tglx>

On 4/21/26 12:17 PM, Thomas Gleixner wrote:
> On Mon, Apr 20 2026 at 23:03, Waiman Long wrote:
>> Add a new cpuhp_offline_cb() API that allows us to offline a set of
>> CPUs one-by-one, run the given callback function and then bring those
>> CPUs back online again while inhibiting any concurrent CPU hotplug
>> operations from happening.
> Please provide a properly structured change log which explains the
> context, the problem and the solution in separate paragraphs and this
> order. This is not new. It's documented...
>
>> This new API can be used to enable runtime adjustment of nohz_full and
>> isolcpus boot command line options. A new cpuhp_offline_cb_mode flag
>> is also added to signal that the system is in this offline callback
>> transient state so that some hotplug operations can be optimized out
>> if we choose to.
> We chose nothing.
>
>> +#include <linux/cpumask_types.h>
> What for? This header only needs a 'struct cpumask' forward declaration
> so that the compiler can handle the pointer argument, no?
>
>> +typedef int (*cpuhp_cb_t)(void *arg);
> You couldn't come up with a more generic name for this, right?
>
>>   struct device;
>>   
>>   extern int lockdep_is_cpus_held(void);
>> @@ -29,6 +31,8 @@ void clear_tasks_mm_cpumask(int cpu);
>>   int remove_cpu(unsigned int cpu);
>>   int cpu_device_down(struct device *dev);
>>   void smp_shutdown_nonboot_cpus(unsigned int primary_cpu);
>> +int cpuhp_offline_cb(struct cpumask *mask, cpuhp_cb_t func, void *arg);
> Ditto.
>
>> +extern bool cpuhp_offline_cb_mode;
> Groan. The only users are in the cpusets code which invokes this muck
> and should therefore know what's going on, no?
>
>>   #else /* CONFIG_HOTPLUG_CPU */
>>   
>> @@ -43,6 +47,11 @@ static inline void cpu_hotplug_disable(void) { }
>>   static inline void cpu_hotplug_enable(void) { }
>>   static inline int remove_cpu(unsigned int cpu) { return -EPERM; }
>>   static inline void smp_shutdown_nonboot_cpus(unsigned int primary_cpu) { }
>> +static inline int cpuhp_offline_cb(struct cpumask *mask, cpuhp_cb_t func, void *arg)
>> +{
>> +	return -EPERM;
> -EPERM?
>
>> +/**
>> + * cpuhp_offline_cb - offline CPUs, invoke callback function & online CPUs afterward
>> + * @mask: A mask of CPUs to be taken offline and then online
>> + * @func: A callback function to be invoked while the given CPUs are offline
>> + * @arg:  Argument to be passed back to the callback function
>> + *
>> + * Return: 0 if successful, an error code otherwise
>> + */
>> +int cpuhp_offline_cb(struct cpumask *mask, cpuhp_cb_t func, void *arg)
>> +{
>> +	int off_cpu, on_cpu, ret, ret2 = 0;
>> +
>> +	if (WARN_ON_ONCE(cpumask_empty(mask) ||
>> +	   !cpumask_subset(mask, cpu_online_mask)))
>> +		return -EINVAL;
> No line break required. You have 100 characters.
>
> But what's worse is that the access to cpu_online_mask is not protected
> against a concurrent CPU hotplug operation.
>
>> +
>> +	pr_debug("%s: begin (CPU list = %*pbl)\n", __func__, cpumask_pr_args(mask));
> Tracing?
>
>> +	lock_device_hotplug();
>> +	cpuhp_offline_cb_mode = true;
>> +	/*
>> +	 * If all offline operations succeed, off_cpu should become nr_cpu_ids.
>> +	 */
>> +	for_each_cpu(off_cpu, mask) {
>> +		ret = device_offline(get_cpu_device(off_cpu));
>> +		if (unlikely(ret))
>> +			break;
>> +	}
>> +	if (!ret)
>> +		ret = func(arg);
>> +
>> +	/* Bring previously offline CPUs back online */
>> +	for_each_cpu(on_cpu, mask) {
>> +		int retries = 0;
>> +
>> +		if (on_cpu == off_cpu)
>> +			break;
>> +
>> +retry:
>> +		ret2 = device_online(get_cpu_device(on_cpu));
>> +
>> +		/*
>> +		 * With the unlikely event that CPU hotplug is disabled while
>> +		 * this operation is in progress, we will need to wait a bit
>> +		 * for hotplug to hopefully be re-enabled again. If not, print
>> +		 * a warning and return the error.
>> +		 *
>> +		 * cpu_hotplug_disabled is supposed to be accessed while
>> +		 * holding the cpu_add_remove_lock mutex. So we need to
>> +		 * use the data_race() macro to access it here.
>> +		 */
>> +		while ((ret2 == -EBUSY) && data_race(cpu_hotplug_disabled) &&
>> +		       (++retries <= 5)) {
>> +			msleep(20);
>> +			if (!data_race(cpu_hotplug_disabled))
>> +				goto retry;
>> +		}
>> +		if (ret2) {
>> +			pr_warn("%s: Failed to bring CPU %d back online!\n",
>> +				__func__, on_cpu);
> Provide a proper text and not this silly __func__ thing.
>
>> +			break;
>> +		}
>> +	}
> TBH. This is unreviewable gunk and the whole 'unlikely event that CPU
> hotplug is disabled' is just a lazy hack.
>
> All of this can be avoided including this made up callback function.
>
> It's not rocket science to provide:
>
>       1) A function which serializes against any other CPU hotplug
>          related action.
>
>       2) A function which brings the CPUs in a given CPU mask down
>
>       3) A function which brings the CPUs in a given CPU mask up
>
>       4) A function which undoes #1
>
> Yeah I know, it's more work and not convoluted enough. But see below.
>
> That brings me to that other hack namely cpuhp_offline_cb_mode, which
> you self described as such in patch 21/23:
>
>> +	/*
>> +	 * Hack: In cpuhp_offline_cb_mode, pretend all partitions are empty
>> +	 * to prevent unnecessary partition invalidation.
>> +	 */
>> +	if (cpuhp_offline_cb_mode)
>> +		return false;
>> +
> We are not merging hacks. End of story. But you knew that already, no?
>
> Let's take a step back and see what you really need to achieve:
>
>    1) Update tick_nohz_full_mask
>    2) Update the managed interrupt mask
>    3) Update CPU sets
>
> Independent of the direction of this update you need to ensure that the
> affected functionality keeps working correctly.
>
> You achieve that by bulk offlining the affected CPUs, invoking a magic
> callback and then bulk onlining the affected CPUs again, which requires
> that ill defined cpuhp_offline_cb_mode hackery and probably some more
> hacks all over the place.
>
> You can achieve the same by doing CPU by CPU operations in the right
> order without this mode hack, when you establish proper limitations for
> this:
>
>    At no point in time it's allowed to empty a CPU set or a affected CPU
>    mask, except when you completely undo the isolation of CPUs.
>
>    That can be computed upfront w/o changing anything at all. Once the
>    validity is established, the update can proceed. Or you can leave it
>    to user space which can keep the pieces if it gets it wrong.
>
> That's a reasonable limitation as there is absolutely zero justification
> to support something like:
>
>         housekeeping_cpus = [CPU 0], isolated_cpus = [CPU 1]
>    ---> housekeeping_cpus = [CPU 1], isolated_cpus = [CPU 0]
>
> just because we can with enough horrible hacks.
>
> If you get that out of the way, then a CPU by CPU update becomes the
> obvious and simplest solution. The ordering constraints can be computed
> in user space upfront and there is no reason to do any of this in the
> kernel itself except for an eventual validation step. It might be a tad
> slower, but this is all but a hotpath operation.
>
> Just for the record. I suggested exactly this more than a year ago and
> it's still the right thing to do.
>
> And of course neither your cover letter nor any of the patches give a
> proper rationale why you think that your bulk hackery is better. For the
> very simple reason that there is no rationale at all.
>
> This bulk muck is doomed when your ultimate goal is to avoid the stop
> machine dance. With a per CPU update it is actually doable without more
> ill defined hacks all over the place.
>
>     1) Bring down the CPU to CPUHP_AP_SCHED_WAIT_EMPTY, which is the last
>        state before stop machine is invoked.
>
>        At that point:
>
>           - no user space thread is running on the CPU anymore
>
>           - everything related to this CPU has been shut down or moved
>             elsewhere
>
>           - interrupt managed device queues are quiesced if the CPU was
>             the last online one in the queue affinity mask. If not the
>             interrupt might still be affine to the CPU, but there is at
>             least one other CPU available in the mask.
>
>     2) Update the tick NOHZ handover
>
>        This can be done without going into stop machine by providing a
>        hotplug callback right between CPUHP_AP_SMPBOOT_THREADS and
>        CPUHP_AP_IRQ_AFFINITY_ONLINE.
>
>        That's trivial enough to achieve and can work independently of
>        NOHZ full.
>
>     3) Rework the affinity management, so that interrupt affinities can
>        be reassigned in the CPUHP_AP_IRQ_AFFINITY_ONLINE state.
>
>        That needs a lot of thoughts, but there is no real reason why it
>        can't work.
>
>     4) Flip the housekeeping CPU masks in sched_cpu_wait_empty() after
>        balance_hotplug_wait().
>
>     5) Bring the CPU online again.
>
> For #2 and #3 to work you need a separate CPU mask which avoids touching
> CPU online mask. For #3 this needs some more work to avoid reassigning the
> interrupts once sparse_irq_lock is dropped, but the bulk is achieved
> with the separate CPU mask.
>
> No?

Thanks for the great suggestions. I will certainly look into that.

We actually have a cpu_active_mask that will be cleared early in 
sched_cpu_deactivate(). In the CPUHP_AP_SCHED_WAIT_EMPTY state, the CPU 
will still have online bit set but the active bit will be cleared. Or we 
could add another cpumask that can be used to indicate CPUs that have 
reached CPUHP_AP_SCHED_WAIT_EMPTY or below if necessary.

Cheers,
Longman


^ permalink raw reply

* Re: [PATCH net v4 2/2] net: airoha: Add missing bits in airoha_qdma_cleanup_tx_queue()
From: Paolo Abeni @ 2026-04-21 17:32 UTC (permalink / raw)
  To: Lorenzo Bianconi
  Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Simon Horman, linux-arm-kernel, linux-mediatek, netdev
In-Reply-To: <aeewoVjN7EHLZTW_@lore-desk>

On 4/21/26 7:15 PM, Lorenzo Bianconi wrote:
>> On 4/17/26 8:36 AM, Lorenzo Bianconi wrote:
>>> @@ -1055,8 +1058,33 @@ static void airoha_qdma_cleanup_tx_queue(struct airoha_queue *q)
>>>  		e->dma_addr = 0;
>>>  		e->skb = NULL;
>>>  		list_add_tail(&e->list, &q->tx_list);
>>> +
>>> +		/* Reset DMA descriptor */
>>> +		WRITE_ONCE(desc->ctrl, 0);
>>> +		WRITE_ONCE(desc->addr, 0);
>>> +		WRITE_ONCE(desc->data, 0);
>>> +		WRITE_ONCE(desc->msg0, 0);
>>> +		WRITE_ONCE(desc->msg1, 0);
>>> +		WRITE_ONCE(desc->msg2, 0);
>>
>> Sashiko has some complains on this patch that look legit to me.
>>
>> Also the pre-existing issues mentioned WRT patch 1/2 makes such patch
>> IMHO almost ineffective, I think you should address them in the same series.
>>
>> Note that you should have commented on sashiko review on the ML, it
>> would have saved a significant amount of time on us.
> 
> Since this series is marked as 'Changes Requested', it is not clear to me what
> next steps are. I guess we have two possible approach here:
> 
> 1) - Post patch 1/2 ("net: airoha: Move ndesc initialization at
>      end of airoha_qdma_init_tx()") with the series available upstream
>      (not merged yet) in [0] where I am fixing similar issues for
>      airoha_qdma_init_rx_queue() and airoha_qdma_tx_irq_init().
>    - Post patch 2/2 ("net: airoha: Add missing bits in
>      airoha_qdma_cleanup_tx_queue()") with a fix for airoha_ndo_stop() waiting
>      for TX/RX DMA engine to complete before running
>      airoha_qdma_cleanup_tx_queue().
> 
> 2) - Since all the issues rised by Sashiko are not strictly related to this
>      series and they are already fixed in pending patches, just apply the fixes
>      separately without the needs to repost this series.

Given the current flood on the ML I think option 2 could be the better.
Note that the tree is currently in Jakub's hands and he can very legitly
disagree.

/P


^ permalink raw reply

* Re: [PATCH net] net: ipv6: fix NOREF dst use in seg6 and rpl lwtunnels
From: Justin Iurman @ 2026-04-21 17:33 UTC (permalink / raw)
  To: Andrea Mayer, davem, dsahern, edumazet, kuba, pabeni, horms
  Cc: bigeasy, clrkwllms, rostedt, david.lebrun, alex.aring,
	stefano.salsano, netdev, linux-rt-devel, linux-kernel, stable
In-Reply-To: <20260421094735.20997-1-andrea.mayer@uniroma2.it>

On 4/21/26 11:47, Andrea Mayer wrote:
> seg6_input_core() and rpl_input() call ip6_route_input() which sets a
> NOREF dst on the skb, then pass it to dst_cache_set_ip6() invoking
> dst_hold() unconditionally.
> On PREEMPT_RT, ksoftirqd is preemptible and a higher-priority task can
> release the underlying pcpu_rt between the lookup and the caching
> through a concurrent FIB lookup on a shared nexthop.
> Simplified race sequence:
> 
>    ksoftirqd/X                       higher-prio task (same CPU X)
>    -----------                       --------------------------------
>    seg6_input_core(,skb)/rpl_input(skb)
>      dst_cache_get()
>        -> miss
>      ip6_route_input(skb)
>        -> ip6_pol_route(,skb,flags)
>           [RT6_LOOKUP_F_DST_NOREF in flags]
>          -> FIB lookup resolves fib6_nh
>             [nhid=N route]
>          -> rt6_make_pcpu_route()
>             [creates pcpu_rt, refcount=1]
>               pcpu_rt->sernum = fib6_sernum
>               [fib6_sernum=W]
>             -> cmpxchg(fib6_nh.rt6i_pcpu,
>                        NULL, pcpu_rt)
>                [slot was empty, store succeeds]
>        -> skb_dst_set_noref(skb, dst)
>           [dst is pcpu_rt, refcount still 1]
> 
>                                      rt_genid_bump_ipv6()
>                                        -> bumps fib6_sernum
>                                           [fib6_sernum from W to Z]
>                                      ip6_route_output()
>                                        -> ip6_pol_route()
>                                          -> FIB lookup resolves fib6_nh
>                                             [nhid=N]
>                                          -> rt6_get_pcpu_route()
>                                               pcpu_rt->sernum != fib6_sernum
>                                               [W <> Z, stale]
>                                            -> prev = xchg(rt6i_pcpu, NULL)
>                                            -> dst_release(prev)
>                                               [prev is pcpu_rt,
>                                                refcount 1->0, dead]
> 
>      dst = skb_dst(skb)
>      [dst is the dead pcpu_rt]
>      dst_cache_set_ip6(dst)
>        -> dst_hold() on dead dst
>        -> WARN / use-after-free
> 
> For the race to occur, ksoftirqd must be preemptible (PREEMPT_RT without
> PREEMPT_RT_NEEDS_BH_LOCK) and a concurrent task must be able to release
> the pcpu_rt. Shared nexthop objects provide such a path, as two routes
> pointing to the same nhid share the same fib6_nh and its rt6i_pcpu
> entry.
> 
> Fix seg6_input_core() and rpl_input() by calling skb_dst_force() after
> ip6_route_input() to force the NOREF dst into a refcounted one before
> caching.
> The output path is not affected as ip6_route_output() already returns a
> refcounted dst.
> 
> Fixes: af4a2209b134 ("ipv6: sr: use dst_cache in seg6_input")
> Fixes: a7a29f9c361f ("net: ipv6: add rpl sr tunnel")
> Cc: stable@vger.kernel.org
> Signed-off-by: Andrea Mayer <andrea.mayer@uniroma2.it>
> ---
>   net/ipv6/rpl_iptunnel.c  | 9 +++++++++
>   net/ipv6/seg6_iptunnel.c | 9 +++++++++
>   2 files changed, 18 insertions(+)
> 
> diff --git a/net/ipv6/rpl_iptunnel.c b/net/ipv6/rpl_iptunnel.c
> index c7942cf65567..4e10adcd70e8 100644
> --- a/net/ipv6/rpl_iptunnel.c
> +++ b/net/ipv6/rpl_iptunnel.c
> @@ -287,7 +287,16 @@ static int rpl_input(struct sk_buff *skb)
>   
>   	if (!dst) {
>   		ip6_route_input(skb);
> +
> +		/* ip6_route_input() sets a NOREF dst; force a refcount on it
> +		 * before caching or further use.
> +		 */
> +		skb_dst_force(skb);
>   		dst = skb_dst(skb);
> +		if (unlikely(!dst)) {
> +			err = -ENETUNREACH;
> +			goto drop;
> +		}
>   
>   		/* cache only if we don't create a dst reference loop */
>   		if (!dst->error && lwtst != dst->lwtstate) {
> diff --git a/net/ipv6/seg6_iptunnel.c b/net/ipv6/seg6_iptunnel.c
> index 97b50d9b1365..94284b483be0 100644
> --- a/net/ipv6/seg6_iptunnel.c
> +++ b/net/ipv6/seg6_iptunnel.c
> @@ -515,7 +515,16 @@ static int seg6_input_core(struct net *net, struct sock *sk,
>   
>   	if (!dst) {
>   		ip6_route_input(skb);
> +
> +		/* ip6_route_input() sets a NOREF dst; force a refcount on it
> +		 * before caching or further use.
> +		 */
> +		skb_dst_force(skb);
>   		dst = skb_dst(skb);
> +		if (unlikely(!dst)) {
> +			err = -ENETUNREACH;
> +			goto drop;
> +		}
>   
>   		/* cache only if we don't create a dst reference loop */
>   		if (!dst->error && lwtst != dst->lwtstate) {

Thanks for taking care of this, Andrea! LGTM.

Reviewed-by: Justin Iurman <justin.iurman@gmail.com>

^ permalink raw reply

* Re: [PATCH net 1/2] net/mlx5e: psp: Fix invalid access on PSP dev registration fail
From: Cosmin Ratiu @ 2026-04-21 17:34 UTC (permalink / raw)
  To: kuba@kernel.org
  Cc: Boris Pismenny, willemdebruijn.kernel@gmail.com,
	andrew+netdev@lunn.ch, daniel.zahka@gmail.com,
	davem@davemloft.net, leon@kernel.org,
	linux-kernel@vger.kernel.org, edumazet@google.com,
	linux-rdma@vger.kernel.org, Rahul Rameshbabu, Raed Salem,
	Dragos Tatulea, kees@kernel.org, Mark Bloch, pabeni@redhat.com,
	Tariq Toukan, Saeed Mahameed, netdev@vger.kernel.org,
	Gal Pressman
In-Reply-To: <20260421080951.570e6e49@kernel.org>

On Tue, 2026-04-21 at 08:09 -0700, Jakub Kicinski wrote:
> On Tue, 21 Apr 2026 14:33:51 +0000 Cosmin Ratiu wrote:
> > > > priv->psp and steering at the time of mlx5e_psp_register() is
> > > > inert
> > > > without the PSP device. Cleaning it on psp_dev_create() failure
> > > > would
> > > > be weird, it's cleaned up anyway on netdev teardown. The fact
> > > > that
> > > > only
> > > > memory allocations can fail inside psp_dev_create() is
> > > > irrelevant
> > > > here.
> > > > psp_dev_create() failing shouldn't bring down the whole
> > > > netdevice,
> > > > so
> > > > logging a message and continuing is ok (which is what is also
> > > > done
> > > > for
> > > > macsec and ktls).  
> > > 
> > > This is a misguided cargo cult. Or something motivated by OOT
> > > compatibility. Alex D sometimes tries to do the same thing with
> > > Meta
> > > drivers. I don't get it. Of course we want the device to be
> > > operational
> > > if some *device* init fails. The compatibility matrix with all
> > > device
> > > generations and fw versions could justify that. But continuing
> > > init
> > > when a single-page kmalloc failed is pure silliness.  
> > 
> > I am not sure about the wider context, but from the POV of the
> > driver,
> > it's calling $thing from the kernel which can fail and it needs to
> > do
> > something about it, either fail the entire netdev bringup or accept
> > that $thing won't be functional and continue without it. The driver
> > shouldn't need to know what $thing does inside and how it can fail,
> > which can change over time. Today it's a kmalloc(), tomorrow it may
> > be
> > something else.
> 
> Like what?

The inner workings of $thing aren't and shouldn't be relevant, no?
Maybe tomorrow the kernel will lazy-init some TCP shenanigans for the
first PSP device being initialized or whatever, or maybe some other
moving parts inside can fail. It's an abstraction, why make it
unnecessarily leaky for the purpose of writing driver code?

> 
> > It doesn't and shouldn't matter for the local decision
> > to continue or not without $thing working.
> > 
> > Isn't this reasonable?
> 
> No, the normal thing to do is to propagate errors.
> If you want to diverge from that _you_ should have a reason,
> a better reason than a vague "kernel can fail".
> I'd prefer for the driver to fail in an obvious way.
> Which will be immediately spotted by the operator, not 2 weeks
> later when 10% of the fleet is upgraded already.
> The only exception I'd make is to keep devlink registered in
> case the fix is to flash a different FW.

In this case, PSP not working would be spotted on the next PSP dev-get
op which produces zilch instead of working devices.

But I understand what you want. You'd like the netdevice to either be
fully initialized with all supported+configured protocols or fail the
open operation. No intermediate/partial states. This is a non-trivial
refactor for mlx5, because mlx5_nic_enable() returns nothing.
Refactoring seems possible though, its only caller is
mlx5e_attach_netdev(), which returns errors. It's certainly not
something that should be done for a net fix though.

I have a series pending for net-next where the PSP configuration is
hooked to mlx5e_psp_set_config(). I will look into implementing what
you propose there and propagate errors.

Meanwhile, do you want to take these fixes (1 and 2) or maybe just 2
for net or not?

Cosmin.

^ permalink raw reply

* Re: [PATCH v2 0/2] Bluetooth: ISO: Fix KCSAN data-races on iso_pi(sk)
From: patchwork-bot+bluetooth @ 2026-04-21 17:40 UTC (permalink / raw)
  To: SeungJu Cheon
  Cc: luiz.dentz, marcel, linux-bluetooth, netdev, linux-kernel, me,
	skhan, linux-kernel-mentees
In-Reply-To: <20260421025122.55781-1-suunj1331@gmail.com>

Hello:

This series was applied to bluetooth/bluetooth-next.git (master)
by Luiz Augusto von Dentz <luiz.von.dentz@intel.com>:

On Tue, 21 Apr 2026 11:51:20 +0900 you wrote:
> Found while auditing iso_pi(sk) field accesses after a KCSAN report.
> Patch 1/2 is the reported race on iso_pi(sk)->dst in iso_sock_connect();
> patch 2/2 covers related races on other iso_pi(sk) fields accessed in
> iso_connect_{bis,cis}() and iso_connect_ind() that were found by
> inspection during the same audit.
> 
> Changes in v2:
>  - Patch 1/2: Use sa->iso_bdaddr directly instead of caching the
>    bacmp() result in a local variable, as suggested by Luiz [1].
>    This avoids reading from iso_pi(sk) entirely for the broadcast
>    check.
> 
> [...]

Here is the summary with links:
  - [v2,1/2] Bluetooth: ISO: Fix data-race on dst in iso_sock_connect()
    https://git.kernel.org/bluetooth/bluetooth-next/c/20ca2749b31a
  - [v2,2/2] Bluetooth: ISO: Fix data-race on iso_pi(sk) in socket and HCI event paths
    https://git.kernel.org/bluetooth/bluetooth-next/c/66d4d518020b

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



^ permalink raw reply

* Re: [PATCH net-deletions] net: remove ax25 and amateur radio (hamradio) subsystem
From: Dan Cross @ 2026-04-21 17:47 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: Jakub Kicinski, davem, netdev, edumazet, pabeni, andrew+netdev,
	horms, corbet, skhan, federico.vaga, carlos.bilbao, avadhut.naik,
	alexs, si.yanteng, dzm91, 2023002089, tsbogend, dsahern,
	jani.nikula, mchehab+huawei, gregkh, jirislaby, tytso, herbert,
	ebiggers, johannes.berg, geert, pablo, tglx, mashiro.chen, mingo,
	dqfext, jreuter, sdf, pkshih, enelsonmoore, mkl, toke, kees,
	jlayton, wangliang74, aha310510, takamitz, kuniyu, linux-doc,
	linux-mips
In-Reply-To: <20260421101400.67545b20@phoenix.local>

On Tue, Apr 21, 2026 at 1:14 PM Stephen Hemminger
<stephen@networkplumber.org> wrote:
> On Tue, 21 Apr 2026 12:17:23 -0400
> Dan Cross <crossd@gmail.com> wrote:
>
> > On Tue, Apr 21, 2026 at 9:55 AM Stephen Hemminger
> > <stephen@networkplumber.org> wrote:
> > > On Mon, 20 Apr 2026 19:18:23 -0700
> > > Jakub Kicinski <kuba@kernel.org> wrote:
> > > > Remove the amateur radio (AX.25, NET/ROM, ROSE) protocol implementation
> > > > and all associated hamradio device drivers from the kernel tree.
> > > > This set of protocols has long been a huge bug/syzbot magnet,
> > > > and since nobody stepped up to help us deal with the influx
> > > > of the AI-generated bug reports we need to move it out of tree
> > > > to protect our sanity.
> > > >
> > > > The code is moved to an out-of-tree repo:
> > > > https://github.com/linux-netdev/mod-orphan
> > > > if it's cleaned up and reworked there we can accept it back.
> > >
> > > It would be good if these protocols could be done in userspace
> > > or with BPF?
> >
> > Consensus for a userspace implementation is what folks on linux-hams
> > seem to be converging on.
> >
> > The amateur radio protocols are more or less specific to low-speed
> > links, they are not particularly coupled to anything else that
> > requires running in the kernel, and the main coupling point (IP over
> > AX.25) can be implemented via TAP/TUN.
> >
> > There are several popular packages that already implement AX.25 and
> > NET/ROM in user-space (for the interested, LinBPQ seems to be the
> > canonical example).  The main missing piece is ROSE, but it is likely
> > easier to add that to an existing package, or potentially something
> > brand new, than keep it in the kernel.
> >
> > There's no compelling reason to keep these protocols in the kernel,
> > whether in-tree or out-of-tree; at least, one has not been
> > articulated.
>
> Thanks, my other concern is carrying support for these in ip commands.
> If not kernel based, then iproute2 doesn't need to worry.

Agreed.

If someone really wants mimic the existing output of those commands in
the context of a userspace implementation, they could write a wrapper
program that invokes the real thing, and extracts relevant information
from the ham protocol implementation, and interpolates it into the
output. It may be an imperfect simulation, but it's probably close
enough for most users.

        - Dan C.

^ permalink raw reply

* [PATCH net] hv_sock: Return -EIO for malformed/short packets
From: Dexuan Cui @ 2026-04-21 17:49 UTC (permalink / raw)
  To: kys, haiyangz, wei.liu, decui, longli, sgarzare, davem, edumazet,
	kuba, pabeni, horms, niuxuewei.nxw, linux-hyperv, virtualization,
	netdev, linux-kernel
  Cc: stable

Commit f63152958994 fixes a regression, however it fails to report an
error for malformed/short packets -- normally we should never see such
packets, but let's report an error for them just in case.

Fixes: f63152958994 ("hv_sock: Report EOF instead of -EIO for FIN")
Cc: stable@vger.kernel.org
Signed-off-by: Dexuan Cui <decui@microsoft.com>
---

Commit f63152958994 is currently only in net.git's master branch.

 net/vmw_vsock/hyperv_transport.c | 29 +++++++++++++++++++----------
 1 file changed, 19 insertions(+), 10 deletions(-)

diff --git a/net/vmw_vsock/hyperv_transport.c b/net/vmw_vsock/hyperv_transport.c
index 76e78c83fdbc..8faaa14bccda 100644
--- a/net/vmw_vsock/hyperv_transport.c
+++ b/net/vmw_vsock/hyperv_transport.c
@@ -704,18 +704,27 @@ static s64 hvs_stream_has_data(struct vsock_sock *vsk)
 		if (hvs->recv_desc) {
 			/* Here hvs->recv_data_len is 0, so hvs->recv_desc must
 			 * be NULL unless it points to the 0-byte-payload FIN
-			 * packet: see hvs_update_recv_data().
+			 * packet or a malformed/short packet: see
+			 * hvs_update_recv_data().
 			 *
-			 * Here all the payload has been dequeued, but
-			 * hvs_channel_readable_payload() still returns 1,
-			 * because the VMBus ringbuffer's read_index is not
-			 * updated for the FIN packet: hvs_stream_dequeue() ->
-			 * hv_pkt_iter_next() updates the cached priv_read_index
-			 * but has no opportunity to update the read_index in
-			 * hv_pkt_iter_close() as hvs_stream_has_data() returns
-			 * 0 for the FIN packet, so it won't get dequeued.
+			 * If hvs->recv_desc points to the FIN packet, here all
+			 * the payload has been dequeued and the peer_shutdown
+			 * flag is set, but hvs_channel_readable_payload() still
+			 * returns 1, because the VMBus ringbuffer's read_index
+			 * is not updated for the FIN packet:
+			 * hvs_stream_dequeue() -> hv_pkt_iter_next() updates
+			 * the cached priv_read_index but has no opportunity to
+			 * update the read_index in hv_pkt_iter_close() as
+			 * hvs_stream_has_data() returns 0 for the FIN packet,
+			 * so it won't get dequeued.
+			 *
+			 * In case hvs->recv_desc points to a malformed/short
+			 * packet, return -EIO.
 			 */
-			return 0;
+			if (hvs->vsk->peer_shutdown & SEND_SHUTDOWN)
+				return 0;
+			else
+				return -EIO;
 		}
 
 		hvs->recv_desc = hv_pkt_iter_first(hvs->chan);
-- 
2.49.0


^ permalink raw reply related

* RE: [EXTERNAL] Re: [PATCH net v2] hv_sock: Report EOF instead of -EIO for FIN
From: Dexuan Cui @ 2026-04-21 17:54 UTC (permalink / raw)
  To: Jakub Kicinski, Stefano Garzarella
  Cc: patchwork-bot+netdevbpf@kernel.org, KY Srinivasan, Haiyang Zhang,
	wei.liu@kernel.org, Long Li, davem@davemloft.net,
	edumazet@google.com, pabeni@redhat.com, horms@kernel.org,
	niuxuewei.nxw@antgroup.com, linux-hyperv@vger.kernel.org,
	virtualization@lists.linux.dev, netdev@vger.kernel.org,
	linux-kernel@vger.kernel.org, stable@vger.kernel.org, Ben Hillis,
	levymitchell0@gmail.com
In-Reply-To: <20260421071839.30217a60@kernel.org>

> From: Jakub Kicinski <kuba@kernel.org>
> Sent: Tuesday, April 21, 2026 7:19 AM
> ...
> > Anyway, let's wait for Jakub's or other net maintainers' suggestions.
> 
> Yes, you have to post an incremental fix

Thanks for the quick replies! I posted an incremental fix:
https://lore.kernel.org/linux-hyperv/20260421174931.1152238-1-decui@microsoft.com/T/#u

^ permalink raw reply

* RE: [PATCH net v3] hv_sock: Report EOF instead of -EIO for FIN
From: Dexuan Cui @ 2026-04-21 17:57 UTC (permalink / raw)
  To: Dexuan Cui, KY Srinivasan, Haiyang Zhang, wei.liu@kernel.org,
	Long Li, sgarzare@redhat.com, davem@davemloft.net,
	edumazet@google.com, kuba@kernel.org, pabeni@redhat.com,
	horms@kernel.org, niuxuewei.nxw@antgroup.com,
	linux-hyperv@vger.kernel.org, virtualization@lists.linux.dev,
	netdev@vger.kernel.org, linux-kernel@vger.kernel.org
  Cc: stable@vger.kernel.org, Ben Hillis, Mitchell Levy
In-Reply-To: <20260421025950.1099495-1-decui@microsoft.com>

> From: Dexuan Cui
> Sent: Monday, April 20, 2026 8:00 PM

Please ignore the email, as I just posted an incremental patch here:
https://lore.kernel.org/linux-hyperv/20260421174931.1152238-1-decui@microsoft.com/T/#u

See the link for more context:
https://lore.kernel.org/linux-hyperv/177672238581.1802062.15838493180057695674.git-patchwork-notify@kernel.org/T/#t

^ permalink raw reply

* Re: [PATCH] gtp: disable BH before calling udp_tunnel_xmit_skb()
From: Justin Iurman @ 2026-04-21 17:58 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: David Carlier, Pablo Neira Ayuso, Harald Welte, Andrew Lunn,
	Eric Dumazet, Paolo Abeni, Weiming Shi, osmocom-net-gprs, netdev,
	linux-kernel, stable
In-Reply-To: <20260420125815.3a920d9a@kernel.org>

On 4/20/26 21:58, Jakub Kicinski wrote:
> On Mon, 20 Apr 2026 21:02:55 +0200 Justin Iurman wrote:
>> On 4/17/26 07:54, David Carlier wrote:
>>> gtp_genl_send_echo_req() runs as a generic netlink doit handler in
>>> process context with BH not disabled. It calls udp_tunnel_xmit_skb(),
>>> which eventually invokes iptunnel_xmit() — that uses __this_cpu_inc/dec
>>> on softnet_data.xmit.recursion to track the tunnel xmit recursion level.
>>>
>>> Without local_bh_disable(), the task may migrate between
>>> dev_xmit_recursion_inc() and dev_xmit_recursion_dec(), breaking the
>>> per-CPU counter pairing. The result is stale or negative recursion
>>> levels that can later produce false-positive
>>> SKB_DROP_REASON_RECURSION_LIMIT drops on either CPU.
>>>
>>> The other udp_tunnel_xmit_skb() call sites in gtp.c are unaffected:
>>> the data path runs under ndo_start_xmit and the echo response handlers
>>> run from the UDP encap rx softirq, both with BH already disabled.
>>>
>>> Fix it by disabling BH around the udp_tunnel_xmit_skb() call, mirroring
>>> commit 2cd7e6971fc2 ("sctp: disable BH before calling
>>> udp_tunnel_xmit_skb()").
>>
>> Why not fix iptunnel_xmit() directly, rather than fixing all possible
>> callers? Basically, jut like we did for lwtunnel_{output|xmit}(). The
>> advantage would be that we no longer have to worry about BHs in the
>> callers, and BHs would only be disabled when necessary.
> 
> Oops, I pushed this already. The bot hasn't caught up yet.
> Let's revisit this if we find another caller in process context?

No worries, works for me!

^ permalink raw reply

* Re: [PATCH net] seg6: fix seg6 lwtunnel output redirect for L2 reduced encap mode
From: Justin Iurman @ 2026-04-21 17:50 UTC (permalink / raw)
  To: Andrea Mayer, davem, dsahern, edumazet, kuba, pabeni, horms
  Cc: anton.makarov11235, stefano.salsano, netdev, linux-kernel, stable
In-Reply-To: <20260418162838.31979-1-andrea.mayer@uniroma2.it>

On 4/18/26 18:28, Andrea Mayer wrote:
> When SEG6_IPTUN_MODE_L2ENCAP_RED (L2ENCAP_RED) was introduced, the
> condition in seg6_build_state() that excludes L2 encap modes from
> setting LWTUNNEL_STATE_OUTPUT_REDIRECT was not updated to account for
> the new mode.
> As a consequence, L2ENCAP_RED routes incorrectly trigger seg6_output()
> on the output path, where the packet is silently dropped because
> skb_mac_header_was_set() fails on L3 packets.
> 
> Extend the check to also exclude L2ENCAP_RED, consistent with L2ENCAP.
> 
> Fixes: 13f0296be8ec ("seg6: add support for SRv6 H.L2Encaps.Red behavior")
> Cc: stable@vger.kernel.org
> Signed-off-by: Andrea Mayer <andrea.mayer@uniroma2.it>
> ---
>   net/ipv6/seg6_iptunnel.c | 3 ++-
>   1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/net/ipv6/seg6_iptunnel.c b/net/ipv6/seg6_iptunnel.c
> index 97b50d9b1365..9b64343ebad6 100644
> --- a/net/ipv6/seg6_iptunnel.c
> +++ b/net/ipv6/seg6_iptunnel.c
> @@ -746,7 +746,8 @@ static int seg6_build_state(struct net *net, struct nlattr *nla,
>   	newts->type = LWTUNNEL_ENCAP_SEG6;
>   	newts->flags |= LWTUNNEL_STATE_INPUT_REDIRECT;
>   
> -	if (tuninfo->mode != SEG6_IPTUN_MODE_L2ENCAP)
> +	if (tuninfo->mode != SEG6_IPTUN_MODE_L2ENCAP &&
> +	    tuninfo->mode != SEG6_IPTUN_MODE_L2ENCAP_RED)
>   		newts->flags |= LWTUNNEL_STATE_OUTPUT_REDIRECT;
>   
>   	newts->headroom = seg6_lwt_headroom(tuninfo);

Reviewed-by: Justin Iurman <justin.iurman@gmail.com>

^ permalink raw reply

* Re: [PATCH] gtp: disable BH before calling udp_tunnel_xmit_skb()
From: Justin Iurman @ 2026-04-21 18:08 UTC (permalink / raw)
  To: David CARLIER
  Cc: Pablo Neira Ayuso, Harald Welte, Andrew Lunn, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Weiming Shi, osmocom-net-gprs,
	netdev, linux-kernel, stable
In-Reply-To: <CA+XhMqyN_fFptjA=8YJtXzyStQZ68xJiNSG464o4R-dQFLHt7w@mail.gmail.com>

On 4/20/26 21:44, David CARLIER wrote:
> Hi Julian,
> 
> On Mon, 20 Apr 2026 at 20:02, Justin Iurman <justin.iurman@gmail.com> wrote:
>>
>> On 4/17/26 07:54, David Carlier wrote:
>>> gtp_genl_send_echo_req() runs as a generic netlink doit handler in
>>> process context with BH not disabled. It calls udp_tunnel_xmit_skb(),
>>> which eventually invokes iptunnel_xmit() — that uses __this_cpu_inc/dec
>>> on softnet_data.xmit.recursion to track the tunnel xmit recursion level.
>>>
>>> Without local_bh_disable(), the task may migrate between
>>> dev_xmit_recursion_inc() and dev_xmit_recursion_dec(), breaking the
>>> per-CPU counter pairing. The result is stale or negative recursion
>>> levels that can later produce false-positive
>>> SKB_DROP_REASON_RECURSION_LIMIT drops on either CPU.
>>>
>>> The other udp_tunnel_xmit_skb() call sites in gtp.c are unaffected:
>>> the data path runs under ndo_start_xmit and the echo response handlers
>>> run from the UDP encap rx softirq, both with BH already disabled.
>>>
>>> Fix it by disabling BH around the udp_tunnel_xmit_skb() call, mirroring
>>> commit 2cd7e6971fc2 ("sctp: disable BH before calling
>>> udp_tunnel_xmit_skb()").
>>
>> Why not fix iptunnel_xmit() directly, rather than fixing all possible
>> callers? Basically, jut like we did for lwtunnel_{output|xmit}(). The
>> advantage would be that we no longer have to worry about BHs in the
>> callers, and BHs would only be disabled when necessary.
> 
> Good point — your lwtunnel fix (c03a49f3093a) is a close parallel, and
>    a central fix would avoid chasing callers one by one (sctp was patched
>    last week, gtp is this one, and tipc/wireguard/ovpn genl paths look
>    similar).
> 
>    Happy to respin as v2 with local_bh_disable/enable moved into
>    iptunnel_xmit() (and ip6tunnel_xmit() for symmetry), and drop the
>    gtp-local hunk. That would also supersede Xin Long's recent sctp
> commit
>    (2cd7e6971fc2), so I'll make sure to Cc him.

Jakub merged it already, so no need to respin. I guess we could revisit 
later if required.

>    One thing I'd like your take on before I send: iptunnel_xmit() feels
>    like the natural home since it owns the recursion counter, but would
>    you rather see it in udp_tunnel_xmit_skb()? I don't want to pick the
>    wrong spot if you already have a preference.

Since udp_tunnel_xmit_skb() is just another caller, I'd definitely do it 
in iptunnel_xmit() to centralize things (same for v6).

^ permalink raw reply

* Re: [PATCH bpf-next] selftests/bpf: drop xdping tool
From: Paul Chaignon @ 2026-04-21 18:21 UTC (permalink / raw)
  To: Alexis Lothoré (eBPF Foundation)
  Cc: Andrii Nakryiko, Eduard Zingerman, Alexei Starovoitov,
	Daniel Borkmann, Martin KaFai Lau, Kumar Kartikeya Dwivedi,
	Song Liu, Yonghong Song, Jiri Olsa, Shuah Khan, David S. Miller,
	Jakub Kicinski, Jesper Dangaard Brouer, John Fastabend,
	Stanislav Fomichev, ebpf, Bastien Curutchet, Thomas Petazzoni,
	linux-kernel, bpf, linux-kselftest, netdev, Alan Maguire
In-Reply-To: <20260417-xdping-v1-1-9b0ce0e7adf8@bootlin.com>

On Fri, Apr 17, 2026 at 05:33:02PM +0200, Alexis Lothoré (eBPF Foundation) wrote:
> As part of a larger cleanup effort in the bpf selftests directory,
> tests and scripts are either being converted to the test_progs framework
> (so they are executed automatically in bpf CI), or removed if not
> relevant for such integration.
> 
> The test_xdping.sh script (with the associated xdping.c) acts as a RTT
> measurement tool, by attaching two small xdp programs to two interfaces.
> Converting this test to test_progs may not make much sense:
> - RTT measurement does not really fit in the scope of a functional test,
>   this is rather about measuring some performance level.
> - there are other existing tests in test_progs that actively validate
>   XDP features like program attachment, return value processing, packet
>   modification, etc
> 
> Drop test_xdping.sh and the corresponding xdping.c userspace part. Keep
> the ebpf part (xdping_kern.c), as it is used by another test integrated
> in test_progs (btf_dump)

The xdping_kern object file is just used in bpf_dump to check we can
parse the license as expected. You can replace that by any other test
with a GPL license (ex., btf_type_tag_percpu.bpf.o) and remove
xdping_kern.c.

[...]


^ permalink raw reply

* Re: [PATCH net 1/2] net/mlx5e: psp: Fix invalid access on PSP dev registration fail
From: Jakub Kicinski @ 2026-04-21 18:32 UTC (permalink / raw)
  To: Cosmin Ratiu
  Cc: Boris Pismenny, willemdebruijn.kernel@gmail.com,
	andrew+netdev@lunn.ch, daniel.zahka@gmail.com,
	davem@davemloft.net, leon@kernel.org,
	linux-kernel@vger.kernel.org, edumazet@google.com,
	linux-rdma@vger.kernel.org, Rahul Rameshbabu, Raed Salem,
	Dragos Tatulea, kees@kernel.org, Mark Bloch, pabeni@redhat.com,
	Tariq Toukan, Saeed Mahameed, netdev@vger.kernel.org,
	Gal Pressman
In-Reply-To: <6d96452f67d5b58578f67f97f750101abd4af9f6.camel@nvidia.com>

On Tue, 21 Apr 2026 17:34:32 +0000 Cosmin Ratiu wrote:
> > No, the normal thing to do is to propagate errors.
> > If you want to diverge from that _you_ should have a reason,
> > a better reason than a vague "kernel can fail".
> > I'd prefer for the driver to fail in an obvious way.
> > Which will be immediately spotted by the operator, not 2 weeks
> > later when 10% of the fleet is upgraded already.
> > The only exception I'd make is to keep devlink registered in
> > case the fix is to flash a different FW.  
> 
> In this case, PSP not working would be spotted on the next PSP dev-get
> op which produces zilch instead of working devices.

When you have X vendors times Y device generations times Z FW versions
in your fleet dev-get returning nothing is not a failure. It just means
you're running on a machine that's not capable. Best you can do to
spot a buggy kernel is to notice that the fraction of PSP traffic is
decreasing over time. After significant portion of the fleet is already
on the bad kernel.

> But I understand what you want. You'd like the netdevice to either be
> fully initialized with all supported+configured protocols or fail the
> open operation. No intermediate/partial states. This is a non-trivial
> refactor for mlx5, because mlx5_nic_enable() returns nothing.
> Refactoring seems possible though, its only caller is
> mlx5e_attach_netdev(), which returns errors. It's certainly not
> something that should be done for a net fix though.
> 
> I have a series pending for net-next where the PSP configuration is
> hooked to mlx5e_psp_set_config(). I will look into implementing what
> you propose there and propagate errors.
> 
> Meanwhile, do you want to take these fixes (1 and 2) or maybe just 2
> for net or not?

Can you call mlx5e_psp_cleanup() when register fails for now?

^ permalink raw reply

* Re: [PATCH v1] net: liquidio: resolve VF pci_dev on demand for FLR requests
From: 최유호 @ 2026-04-21 18:39 UTC (permalink / raw)
  To: Simon Horman
  Cc: David S . Miller, Jakub Kicinski, Paolo Abeni, netdev,
	Andrew Lunn, Eric Dumazet, Kory Maincent, Vadim Fedorenko,
	Marco Crivellari, linux-kernel, Myeonghun Pak, Ijae Kim,
	Taegyu Kim
In-Reply-To: <20260421153338.GE651125@horms.kernel.org>

Dear Simon,

Thanks for pointing out the correct tree target and the linker error
on net-next.
I will rework this, targeting 'net' and ensuring the necessary
functions are handled correctly.

Best regards,

On Tue, 21 Apr 2026 at 11:33, Simon Horman <horms@kernel.org> wrote:
>
> On Sun, Apr 19, 2026 at 10:33:04PM -0400, Yuho Choi wrote:
> > The PF SR-IOV enable path caches VF pci_dev pointers in
> > dpiring_to_vfpcidev_lut[] by iterating with pci_get_device(). Those
> > entries do not own a reference, because the iterator drops the previous
> > device reference on each step. The cached pointer is then dereferenced
> > later when handling OCTEON_VF_FLR_REQUEST.
> >
> > This can leave stale VF pci_dev pointers in the lookup table and makes
> > the FLR path rely on a PCI device object whose lifetime is not pinned.
> >
> > Drop the long-lived lookup table and resolve the VF pci_dev only when an
> > FLR request arrives. Use the PF's SR-IOV metadata to derive the VF's
> > bus/devfn, get a referenced pci_dev for immediate use, issue the FLR,
> > and then drop the reference.
> >
> > Fixes: ca6139ffc67ee ("liquidio CN23XX: sysfs VF config support")
> > Fixes: 8c978d059224 ("liquidio CN23XX: Mailbox support")
> > Co-developed-by: Myeonghun Pak <mhun512@gmail.com>
> > Signed-off-by: Myeonghun Pak <mhun512@gmail.com>
> > Co-developed-by: Ijae Kim <ae878000@gmail.com>
> > Signed-off-by: Ijae Kim <ae878000@gmail.com>
> > Co-developed-by: Taegyu Kim <tmk5904@psu.edu>
> > Signed-off-by: Taegyu Kim <tmk5904@psu.edu>
> > Signed-off-by: Yuho Choi <dbgh9129@gmail.com>
>
> As this fixes code present in the net tree, it should be targeted
> at that tree, like this:
>
> Subject: [PATCH net] ...
>
> In this case the CI defaulted to the net-next tree.
> Which might be harmless. But please keep this in mind for next time.
>
> ...
>
> > diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_mailbox.c b/drivers/net/ethernet/cavium/liquidio/octeon_mailbox.c
> > index ad685f5d0a136..b967c7928b4a7 100644
> > --- a/drivers/net/ethernet/cavium/liquidio/octeon_mailbox.c
> > +++ b/drivers/net/ethernet/cavium/liquidio/octeon_mailbox.c
> > @@ -26,6 +26,29 @@
> >  #include "octeon_mailbox.h"
> >  #include "cn23xx_pf_device.h"
> >
> > +static struct pci_dev *lio_vf_pci_dev_by_qno(struct octeon_device *oct, u32 q_no)
> > +{
> > +     int vfidx, bus, devfn;
> > +
> > +     if (!oct->sriov_info.rings_per_vf)
> > +             return NULL;
> > +
> > +     if (q_no % oct->sriov_info.rings_per_vf)
> > +             return NULL;
> > +
> > +     vfidx = q_no / oct->sriov_info.rings_per_vf;
> > +     if (vfidx >= oct->sriov_info.num_vfs_alloced)
> > +             return NULL;
> > +
> > +     bus = pci_iov_virtfn_bus(oct->pci_dev, vfidx);
>
> When applied against net-next this causes a linker error with x86_64
> allmodconfig (at least) because pci_iov_virtfn_bus is not defined.
>
> > +     devfn = pci_iov_virtfn_devfn(oct->pci_dev, vfidx);
> > +     if (bus < 0 || devfn < 0)
> > +             return NULL;
> > +
> > +     return pci_get_domain_bus_and_slot(pci_domain_nr(oct->pci_dev->bus),
> > +                                        bus, devfn);
> > +}
> > +
> >  /**
> >   * octeon_mbox_read:
> >   * @mbox: Pointer mailbox
>
> --
> pw-bot: changes-requested

^ permalink raw reply

* Re: [PATCH bpf-next] selftests/bpf: drop xdping tool
From: Alexis Lothoré @ 2026-04-21 18:39 UTC (permalink / raw)
  To: Paul Chaignon, Alexis Lothoré (eBPF Foundation)
  Cc: Andrii Nakryiko, Eduard Zingerman, Alexei Starovoitov,
	Daniel Borkmann, Martin KaFai Lau, Kumar Kartikeya Dwivedi,
	Song Liu, Yonghong Song, Jiri Olsa, Shuah Khan, David S. Miller,
	Jakub Kicinski, Jesper Dangaard Brouer, John Fastabend,
	Stanislav Fomichev, ebpf, Bastien Curutchet, Thomas Petazzoni,
	linux-kernel, bpf, linux-kselftest, netdev, Alan Maguire
In-Reply-To: <aefAHLdVZaOmf1Os@mail.gmail.com>

Hi Paul,
thanks for the feedback.

On Tue Apr 21, 2026 at 8:21 PM CEST, Paul Chaignon wrote:
> On Fri, Apr 17, 2026 at 05:33:02PM +0200, Alexis Lothoré (eBPF Foundation) wrote:

[...]

>> Drop test_xdping.sh and the corresponding xdping.c userspace part. Keep
>> the ebpf part (xdping_kern.c), as it is used by another test integrated
>> in test_progs (btf_dump)
>
> The xdping_kern object file is just used in bpf_dump to check we can
> parse the license as expected. You can replace that by any other test
> with a GPL license (ex., btf_type_tag_percpu.bpf.o) and remove
> xdping_kern.c.

Indeed. I'll let a bit of time in case anyone finally advocates to make
xdping stay, otherwise I'll send a v2 making the btf_dump test use
another prog meant to stay, so that I can also drop the xdping_kern
prog.

Thanks,

Alexis

-- 
Alexis Lothoré, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com


^ permalink raw reply

* Re: [PATCH 18/23] cpu/hotplug: Add a new cpuhp_offline_cb() API
From: Thomas Gleixner @ 2026-04-21 18:43 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,
	Chen Ridong, 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: <4a0ede3e-6e87-414f-a3a3-dd15c32f25ef@redhat.com>

On Tue, Apr 21 2026 at 13:29, Waiman Long wrote:
> On 4/21/26 12:17 PM, Thomas Gleixner wrote:
> Thanks for the great suggestions. I will certainly look into that.
>
> We actually have a cpu_active_mask that will be cleared early in 
> sched_cpu_deactivate(). In the CPUHP_AP_SCHED_WAIT_EMPTY state, the CPU 
> will still have online bit set but the active bit will be cleared. Or we 
> could add another cpumask that can be used to indicate CPUs that have 
> reached CPUHP_AP_SCHED_WAIT_EMPTY or below if necessary.

Right. Active mask is immediately cleared when a CPU goes down so that
the scheduler does not enqueue new tasks on it. But you can't use it for
interrupts because on CPU up the mask must be up to date when
irq_affinity_online_cpu() is invoked. The tick has the same constraints.

So for interrupts this should be handled in CPUHP_AP_IRQ_AFFINITY_ONLINE
both in the existing up and the new down callback. That can be a
interrupt core local CPU mask which is updated on the callbacks with the
sparse_irq_lock held.

Same for the tick handover magic.

Thanks,

        tglx

^ permalink raw reply

* Re: [syzbot] [kvm?] [net?] [virt?] BUG: sleeping function called from invalid context in vhost_get_avail_idx
From: syzbot @ 2026-04-21 19:03 UTC (permalink / raw)
  To: jasowang, kohei, linux-kernel, mst, netdev, syzkaller-bugs
In-Reply-To: <aeerTzpq8B-WTKeC@x1>

Hello,

syzbot tried to test the proposed patch but the build/boot failed:

failed to copy syz-execprog to VM: scp failed: failed to run ["scp" "-P" "36338" "-F" "/dev/null" "-o" "UserKnownHostsFile=/dev/null" "-o" "IdentitiesOnly=yes" "-o" "BatchMode=yes" "-o" "StrictHostKeyChecking=no" "-o" "ConnectTimeout=10" "-v" "/syzkaller/jobs/linux/gopath/src/github.com/google/syzkaller/bin/linux_amd64/syz-execprog" "root@localhost:/syz-execprog"]: exit status 1



syzkaller build log:
go env (err=<nil>)
AR='ar'
CC='gcc'
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_ENABLED='1'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
CXX='g++'
GCCGO='gccgo'
GO111MODULE='auto'
GOAMD64='v1'
GOARCH='amd64'
GOAUTH='netrc'
GOBIN=''
GOCACHE='/syzkaller/.cache/go-build'
GOCACHEPROG=''
GODEBUG=''
GOENV='/syzkaller/.config/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFIPS140='off'
GOFLAGS=''
GOGCCFLAGS='-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=/tmp/go-build4123752491=/tmp/go-build -gno-record-gcc-switches'
GOHOSTARCH='amd64'
GOHOSTOS='linux'
GOINSECURE=''
GOMOD='/syzkaller/jobs/linux/gopath/src/github.com/google/syzkaller/go.mod'
GOMODCACHE='/syzkaller/jobs/linux/gopath/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='linux'
GOPATH='/syzkaller/jobs/linux/gopath'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/usr/local/go'
GOSUMDB='sum.golang.org'
GOTELEMETRY='local'
GOTELEMETRYDIR='/syzkaller/.config/go/telemetry'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/usr/local/go/pkg/tool/linux_amd64'
GOVCS=''
GOVERSION='go1.26.0'
GOWORK=''
PKG_CONFIG='pkg-config'

git status (err=<nil>)
HEAD detached at 5be7a9deb87
nothing to commit, working tree clean


tput: No value for $TERM and no -T specified
tput: No value for $TERM and no -T specified
Makefile:31: run command via tools/syz-env for best compatibility, see:
Makefile:32: https://github.com/google/syzkaller/blob/master/docs/contributing.md#using-syz-env
go list -f '{{.Stale}}' -ldflags="-s -w -X github.com/google/syzkaller/prog.GitRevision=5be7a9deb87612d05fcc86125226d72bc2297875 -X github.com/google/syzkaller/prog.gitRevisionDate=20260417-202028"  ./sys/syz-sysgen | grep -q false || go install -ldflags="-s -w -X github.com/google/syzkaller/prog.GitRevision=5be7a9deb87612d05fcc86125226d72bc2297875 -X github.com/google/syzkaller/prog.gitRevisionDate=20260417-202028"  ./sys/syz-sysgen
make .descriptions
tput: No value for $TERM and no -T specified
tput: No value for $TERM and no -T specified
Makefile:31: run command via tools/syz-env for best compatibility, see:
Makefile:32: https://github.com/google/syzkaller/blob/master/docs/contributing.md#using-syz-env
bin/syz-sysgen
touch .descriptions
GOOS=linux GOARCH=amd64 go build -ldflags="-s -w -X github.com/google/syzkaller/prog.GitRevision=5be7a9deb87612d05fcc86125226d72bc2297875 -X github.com/google/syzkaller/prog.gitRevisionDate=20260417-202028"  -o ./bin/linux_amd64/syz-execprog github.com/google/syzkaller/tools/syz-execprog
mkdir -p ./bin/linux_amd64
g++ -o ./bin/linux_amd64/syz-executor executor/executor.cc \
	-m64 -O2 -pthread -Wall -Werror -Wparentheses -Wunused-const-variable -Wframe-larger-than=16384 -Wno-stringop-overflow -Wno-array-bounds -Wno-format-overflow -Wno-unused-but-set-variable -Wno-unused-command-line-argument -static-pie -std=c++17 -I. -Iexecutor/_include   -DGOOS_linux=1 -DGOARCH_amd64=1 \
	-DHOSTGOOS_linux=1 -DGIT_REVISION=\"5be7a9deb87612d05fcc86125226d72bc2297875\"
/usr/bin/ld: /tmp/ccUDlBPa.o: in function `Connection::Connect(char const*, char const*)':
executor.cc:(.text._ZN10Connection7ConnectEPKcS1_[_ZN10Connection7ConnectEPKcS1_]+0x386): warning: Using 'gethostbyname' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
./tools/check-syzos.sh 2>/dev/null



Tested on:

commit:         4ee64205 Merge tag 'clk-for-linus' of git://git.kernel..
git tree:       upstream
kernel config:  https://syzkaller.appspot.com/x/.config?x=95ee3fe1c5a8ab57
dashboard link: https://syzkaller.appspot.com/bug?extid=6985cb8e543ea90ba8ee
compiler:       gcc (Debian 14.2.0-19) 14.2.0, GNU ld (GNU Binutils for Debian) 2.44
patch:          https://syzkaller.appspot.com/x/patch.diff?x=122eb4ce580000


^ permalink raw reply

* [PATCH net 00/18] Remove a number of ISA and PCMCIA Ethernet drivers
From: Andrew Lunn @ 2026-04-21 19:31 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

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.

These are all ISA and PCMCIA Ethernet devices, mostly from the last
century, a couple from 2001 or 2002. It seems unlikely they are still
used. However, remove them one patch at a time so they can be brought
back if somebody still has the hardware, runs modern kernels and wants
to take up the roll of driver Maintainer.

Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
Andrew Lunn (18):
      drivers: net: 3com: 3c509: Remove this driver
      drivers: net: 3com: 3c515: Remove this driver
      drivers: net: 3com: 3c574: Remove this driver
      drivers: net: 3com: 3c589: Remove this driver
      drivers: net: 3com: 3c59x: Remove this driver
      drivers: net: amd: Remove hplance and mvme147
      drivers: net: amd: lance: Remove this driver
      drivers: net: amd: nmclan: Remove this driver
      drivers: net: smsc: smc9194: Remove this driver
      drivers: net: smsc: smc91c92: Remove this driver
      drivers: net: cirrus: cs89x0: Remove this driver
      drivers: net: cirrus: mac89x0: Remove this driver
      drivers: net: fujitsu: fmvj18x: Remove this driver
      drivers: net: xircom: xirc2ps: Remove this driver
      drivers: net: 8390: AX88190: Remove this driver
      drivers: net: 8390: pcnet: Remove this driver
      drivers: net: 8390: ultra: Remove this driver
      drivers: net: 8390: wd80x3: Remove this driver

 .../device_drivers/ethernet/3com/vortex.rst        |  459 ---
 MAINTAINERS                                        |    7 -
 drivers/net/ethernet/3com/3c509.c                  | 1448 ---------
 drivers/net/ethernet/3com/3c515.c                  | 1566 ---------
 drivers/net/ethernet/3com/3c574_cs.c               | 1164 -------
 drivers/net/ethernet/3com/3c589_cs.c               |  974 ------
 drivers/net/ethernet/3com/3c59x.c                  | 3357 --------------------
 drivers/net/ethernet/3com/Kconfig                  |   66 -
 drivers/net/ethernet/3com/Makefile                 |    5 -
 drivers/net/ethernet/8390/Kconfig                  |   52 -
 drivers/net/ethernet/8390/Makefile                 |    4 -
 drivers/net/ethernet/8390/axnet_cs.c               | 1707 ----------
 drivers/net/ethernet/8390/pcnet_cs.c               | 1717 ----------
 drivers/net/ethernet/8390/smc-ultra.c              |  630 ----
 drivers/net/ethernet/8390/wd.c                     |  575 ----
 drivers/net/ethernet/Kconfig                       |    2 -
 drivers/net/ethernet/amd/7990.c                    |  671 ----
 drivers/net/ethernet/amd/7990.h                    |  251 --
 drivers/net/ethernet/amd/Kconfig                   |   39 -
 drivers/net/ethernet/amd/Makefile                  |    4 -
 drivers/net/ethernet/amd/hplance.c                 |  238 --
 drivers/net/ethernet/amd/hplance.h                 |   27 -
 drivers/net/ethernet/amd/lance.c                   | 1317 --------
 drivers/net/ethernet/amd/mvme147.c                 |  198 --
 drivers/net/ethernet/amd/nmclan_cs.c               | 1508 ---------
 drivers/net/ethernet/cirrus/Kconfig                |   40 -
 drivers/net/ethernet/cirrus/Makefile               |    2 -
 drivers/net/ethernet/cirrus/cs89x0.c               | 1915 -----------
 drivers/net/ethernet/cirrus/cs89x0.h               |  461 ---
 drivers/net/ethernet/cirrus/mac89x0.c              |  577 ----
 drivers/net/ethernet/fujitsu/Kconfig               |   30 -
 drivers/net/ethernet/fujitsu/Makefile              |    6 -
 drivers/net/ethernet/fujitsu/fmvj18x_cs.c          | 1176 -------
 drivers/net/ethernet/smsc/Kconfig                  |   27 -
 drivers/net/ethernet/smsc/Makefile                 |    2 -
 drivers/net/ethernet/smsc/smc9194.c                | 1535 ---------
 drivers/net/ethernet/smsc/smc91c92_cs.c            | 2059 ------------
 drivers/net/ethernet/xircom/Kconfig                |   30 -
 drivers/net/ethernet/xircom/Makefile               |    6 -
 drivers/net/ethernet/xircom/xirc2ps_cs.c           | 1794 -----------
 40 files changed, 27646 deletions(-)
---
base-commit: 1f5ffc672165ff851063a5fd044b727ab2517ae3
change-id: 20260421-v7-0-0-net-next-driver-removal-v1-47c88c987b34

Best regards,
-- 
Andrew Lunn <andrew@lunn.ch>


^ permalink raw reply

* [PATCH net 02/18] drivers: net: 3com: 3c515: Remove this driver
From: Andrew Lunn @ 2026-04-21 19:31 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
In-Reply-To: <20260421-v7-0-0-net-next-driver-removal-v1-v1-0-69517c689d1f@lunn.ch>

The 3c515 was written by Donald Becker between 1997-1998. It is an ISA
device, so unlikely to be used with modern kernels.

Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
 drivers/net/ethernet/3com/3c515.c  | 1566 ------------------------------------
 drivers/net/ethernet/3com/Kconfig  |   11 -
 drivers/net/ethernet/3com/Makefile |    1 -
 3 files changed, 1578 deletions(-)

diff --git a/drivers/net/ethernet/3com/3c515.c b/drivers/net/ethernet/3com/3c515.c
deleted file mode 100644
index 2227c83a4862..000000000000
--- a/drivers/net/ethernet/3com/3c515.c
+++ /dev/null
@@ -1,1566 +0,0 @@
-/*
-	Written 1997-1998 by Donald Becker.
-
-	This software may be used and distributed according to the terms
-	of the GNU General Public License, incorporated herein by reference.
-
-	This driver is for the 3Com ISA EtherLink XL "Corkscrew" 3c515 ethercard.
-
-	The author may be reached as becker@scyld.com, or C/O
-	Scyld Computing Corporation
-	410 Severn Ave., Suite 210
-	Annapolis MD 21403
-
-
-	2000/2/2- Added support for kernel-level ISAPnP
-		by Stephen Frost <sfrost@snowman.net> and Alessandro Zummo
-	Cleaned up for 2.3.x/softnet by Jeff Garzik and Alan Cox.
-
-	2001/11/17 - Added ethtool support (jgarzik)
-
-	2002/10/28 - Locking updates for 2.5 (alan@lxorguk.ukuu.org.uk)
-
-*/
-
-#define DRV_NAME		"3c515"
-
-#define CORKSCREW 1
-
-/* "Knobs" that adjust features and parameters. */
-/* Set the copy breakpoint for the copy-only-tiny-frames scheme.
-   Setting to > 1512 effectively disables this feature. */
-static int rx_copybreak = 200;
-
-/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
-static int max_interrupt_work = 20;
-
-/* Enable the automatic media selection code -- usually set. */
-#define AUTOMEDIA 1
-
-/* Allow the use of fragment bus master transfers instead of only
-   programmed-I/O for Vortex cards.  Full-bus-master transfers are always
-   enabled by default on Boomerang cards.  If VORTEX_BUS_MASTER is defined,
-   the feature may be turned on using 'options'. */
-#define VORTEX_BUS_MASTER
-
-/* A few values that may be tweaked. */
-/* Keep the ring sizes a power of two for efficiency. */
-#define TX_RING_SIZE	16
-#define RX_RING_SIZE	16
-#define PKT_BUF_SZ		1536	/* Size of each temporary Rx buffer. */
-
-#include <linux/module.h>
-#include <linux/isapnp.h>
-#include <linux/kernel.h>
-#include <linux/netdevice.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/in.h>
-#include <linux/ioport.h>
-#include <linux/skbuff.h>
-#include <linux/etherdevice.h>
-#include <linux/interrupt.h>
-#include <linux/timer.h>
-#include <linux/ethtool.h>
-#include <linux/bitops.h>
-#include <linux/uaccess.h>
-
-#include <net/Space.h>
-
-#include <asm/io.h>
-#include <asm/dma.h>
-
-#define NEW_MULTICAST
-#include <linux/delay.h>
-
-#define MAX_UNITS 8
-
-MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
-MODULE_DESCRIPTION("3Com 3c515 Corkscrew driver");
-MODULE_LICENSE("GPL");
-
-/* "Knobs" for adjusting internal parameters. */
-/* Put out somewhat more debugging messages. (0 - no msg, 1 minimal msgs). */
-#define DRIVER_DEBUG 1
-/* Some values here only for performance evaluation and path-coverage
-   debugging. */
-static int rx_nocopy, rx_copy, queued_packet;
-
-/* Number of times to check to see if the Tx FIFO has space, used in some
-   limited cases. */
-#define WAIT_TX_AVAIL 200
-
-/* Operational parameter that usually are not changed. */
-#define TX_TIMEOUT  ((4*HZ)/10)	/* Time in jiffies before concluding Tx hung */
-
-/* The size here is somewhat misleading: the Corkscrew also uses the ISA
-   aliased registers at <base>+0x400.
-   */
-#define CORKSCREW_TOTAL_SIZE 0x20
-
-#ifdef DRIVER_DEBUG
-static int corkscrew_debug = DRIVER_DEBUG;
-#else
-static int corkscrew_debug = 1;
-#endif
-
-#define CORKSCREW_ID 10
-
-/*
-				Theory of Operation
-
-I. Board Compatibility
-
-This device driver is designed for the 3Com 3c515 ISA Fast EtherLink XL,
-3Com's ISA bus adapter for Fast Ethernet.  Due to the unique I/O port layout,
-it's not practical to integrate this driver with the other EtherLink drivers.
-
-II. Board-specific settings
-
-The Corkscrew has an EEPROM for configuration, but no special settings are
-needed for Linux.
-
-III. Driver operation
-
-The 3c515 series use an interface that's very similar to the 3c900 "Boomerang"
-PCI cards, with the bus master interface extensively modified to work with
-the ISA bus.
-
-The card is capable of full-bus-master transfers with separate
-lists of transmit and receive descriptors, similar to the AMD LANCE/PCnet,
-DEC Tulip and Intel Speedo3.
-
-This driver uses a "RX_COPYBREAK" scheme rather than a fixed intermediate
-receive buffer.  This scheme allocates full-sized skbuffs as receive
-buffers.  The value RX_COPYBREAK is used as the copying breakpoint: it is
-chosen to trade-off the memory wasted by passing the full-sized skbuff to
-the queue layer for all frames vs. the copying cost of copying a frame to a
-correctly-sized skbuff.
-
-
-IIIC. Synchronization
-The driver runs as two independent, single-threaded flows of control.  One
-is the send-packet routine, which enforces single-threaded use by the netif
-layer.  The other thread is the interrupt handler, which is single
-threaded by the hardware and other software.
-
-IV. Notes
-
-Thanks to Terry Murphy of 3Com for providing documentation and a development
-board.
-
-The names "Vortex", "Boomerang" and "Corkscrew" are the internal 3Com
-project names.  I use these names to eliminate confusion -- 3Com product
-numbers and names are very similar and often confused.
-
-The new chips support both ethernet (1.5K) and FDDI (4.5K) frame sizes!
-This driver only supports ethernet frames because of the recent MTU limit
-of 1.5K, but the changes to support 4.5K are minimal.
-*/
-
-/* Operational definitions.
-   These are not used by other compilation units and thus are not
-   exported in a ".h" file.
-
-   First the windows.  There are eight register windows, with the command
-   and status registers available in each.
-   */
-#define EL3WINDOW(win_num) outw(SelectWindow + (win_num), ioaddr + EL3_CMD)
-#define EL3_CMD 0x0e
-#define EL3_STATUS 0x0e
-
-/* The top five bits written to EL3_CMD are a command, the lower
-   11 bits are the parameter, if applicable.
-   Note that 11 parameters bits was fine for ethernet, but the new chips
-   can handle FDDI length frames (~4500 octets) and now parameters count
-   32-bit 'Dwords' rather than octets. */
-
-enum corkscrew_cmd {
-	TotalReset = 0 << 11, SelectWindow = 1 << 11, StartCoax = 2 << 11,
-	RxDisable = 3 << 11, RxEnable = 4 << 11, RxReset = 5 << 11,
-	UpStall = 6 << 11, UpUnstall = (6 << 11) + 1, DownStall = (6 << 11) + 2,
-	DownUnstall = (6 << 11) + 3, RxDiscard = 8 << 11, TxEnable = 9 << 11,
-	TxDisable = 10 << 11, TxReset = 11 << 11, FakeIntr = 12 << 11,
-	AckIntr = 13 << 11, SetIntrEnb = 14 << 11, SetStatusEnb = 15 << 11,
-	SetRxFilter = 16 << 11, SetRxThreshold = 17 << 11,
-	SetTxThreshold = 18 << 11, SetTxStart = 19 << 11, StartDMAUp = 20 << 11,
-	StartDMADown = (20 << 11) + 1, StatsEnable = 21 << 11,
-	StatsDisable = 22 << 11, StopCoax = 23 << 11,
-};
-
-/* The SetRxFilter command accepts the following classes: */
-enum RxFilter {
-	RxStation = 1, RxMulticast = 2, RxBroadcast = 4, RxProm = 8
-};
-
-/* Bits in the general status register. */
-enum corkscrew_status {
-	IntLatch = 0x0001, AdapterFailure = 0x0002, TxComplete = 0x0004,
-	TxAvailable = 0x0008, RxComplete = 0x0010, RxEarly = 0x0020,
-	IntReq = 0x0040, StatsFull = 0x0080,
-	DMADone = 1 << 8, DownComplete = 1 << 9, UpComplete = 1 << 10,
-	DMAInProgress = 1 << 11,	/* DMA controller is still busy. */
-	CmdInProgress = 1 << 12,	/* EL3_CMD is still busy. */
-};
-
-/* Register window 1 offsets, the window used in normal operation.
-   On the Corkscrew this window is always mapped at offsets 0x10-0x1f. */
-enum Window1 {
-	TX_FIFO = 0x10, RX_FIFO = 0x10, RxErrors = 0x14,
-	RxStatus = 0x18, Timer = 0x1A, TxStatus = 0x1B,
-	TxFree = 0x1C,		/* Remaining free bytes in Tx buffer. */
-};
-enum Window0 {
-	Wn0IRQ = 0x08,
-#if defined(CORKSCREW)
-	Wn0EepromCmd = 0x200A,	/* Corkscrew EEPROM command register. */
-	Wn0EepromData = 0x200C,	/* Corkscrew EEPROM results register. */
-#else
-	Wn0EepromCmd = 10,	/* Window 0: EEPROM command register. */
-	Wn0EepromData = 12,	/* Window 0: EEPROM results register. */
-#endif
-};
-enum Win0_EEPROM_bits {
-	EEPROM_Read = 0x80, EEPROM_WRITE = 0x40, EEPROM_ERASE = 0xC0,
-	EEPROM_EWENB = 0x30,	/* Enable erasing/writing for 10 msec. */
-	EEPROM_EWDIS = 0x00,	/* Disable EWENB before 10 msec timeout. */
-};
-
-/* EEPROM locations. */
-enum eeprom_offset {
-	PhysAddr01 = 0, PhysAddr23 = 1, PhysAddr45 = 2, ModelID = 3,
-	EtherLink3ID = 7,
-};
-
-enum Window3 {			/* Window 3: MAC/config bits. */
-	Wn3_Config = 0, Wn3_MAC_Ctrl = 6, Wn3_Options = 8,
-};
-enum wn3_config {
-	Ram_size = 7,
-	Ram_width = 8,
-	Ram_speed = 0x30,
-	Rom_size = 0xc0,
-	Ram_split_shift = 16,
-	Ram_split = 3 << Ram_split_shift,
-	Xcvr_shift = 20,
-	Xcvr = 7 << Xcvr_shift,
-	Autoselect = 0x1000000,
-};
-
-enum Window4 {
-	Wn4_NetDiag = 6, Wn4_Media = 10,	/* Window 4: Xcvr/media bits. */
-};
-enum Win4_Media_bits {
-	Media_SQE = 0x0008,	/* Enable SQE error counting for AUI. */
-	Media_10TP = 0x00C0,	/* Enable link beat and jabber for 10baseT. */
-	Media_Lnk = 0x0080,	/* Enable just link beat for 100TX/100FX. */
-	Media_LnkBeat = 0x0800,
-};
-enum Window7 {			/* Window 7: Bus Master control. */
-	Wn7_MasterAddr = 0, Wn7_MasterLen = 6, Wn7_MasterStatus = 12,
-};
-
-/* Boomerang-style bus master control registers.  Note ISA aliases! */
-enum MasterCtrl {
-	PktStatus = 0x400, DownListPtr = 0x404, FragAddr = 0x408, FragLen =
-	    0x40c,
-	TxFreeThreshold = 0x40f, UpPktStatus = 0x410, UpListPtr = 0x418,
-};
-
-/* The Rx and Tx descriptor lists.
-   Caution Alpha hackers: these types are 32 bits!  Note also the 8 byte
-   alignment contraint on tx_ring[] and rx_ring[]. */
-struct boom_rx_desc {
-	u32 next;
-	s32 status;
-	u32 addr;
-	s32 length;
-};
-
-/* Values for the Rx status entry. */
-enum rx_desc_status {
-	RxDComplete = 0x00008000, RxDError = 0x4000,
-	/* See boomerang_rx() for actual error bits */
-};
-
-struct boom_tx_desc {
-	u32 next;
-	s32 status;
-	u32 addr;
-	s32 length;
-};
-
-struct corkscrew_private {
-	const char *product_name;
-	struct list_head list;
-	struct net_device *our_dev;
-	/* The Rx and Tx rings are here to keep them quad-word-aligned. */
-	struct boom_rx_desc rx_ring[RX_RING_SIZE];
-	struct boom_tx_desc tx_ring[TX_RING_SIZE];
-	/* The addresses of transmit- and receive-in-place skbuffs. */
-	struct sk_buff *rx_skbuff[RX_RING_SIZE];
-	struct sk_buff *tx_skbuff[TX_RING_SIZE];
-	unsigned int cur_rx, cur_tx;	/* The next free ring entry */
-	unsigned int dirty_rx, dirty_tx;/* The ring entries to be free()ed. */
-	struct sk_buff *tx_skb;	/* Packet being eaten by bus master ctrl.  */
-	struct timer_list timer;	/* Media selection timer. */
-	int capabilities	;	/* Adapter capabilities word. */
-	int options;			/* User-settable misc. driver options. */
-	int last_rx_packets;		/* For media autoselection. */
-	unsigned int available_media:8,	/* From Wn3_Options */
-		media_override:3,	/* Passed-in media type. */
-		default_media:3,	/* Read from the EEPROM. */
-		full_duplex:1, autoselect:1, bus_master:1,	/* Vortex can only do a fragment bus-m. */
-		full_bus_master_tx:1, full_bus_master_rx:1,	/* Boomerang  */
-		tx_full:1;
-	spinlock_t lock;
-	struct device *dev;
-};
-
-/* The action to take with a media selection timer tick.
-   Note that we deviate from the 3Com order by checking 10base2 before AUI.
- */
-enum xcvr_types {
-	XCVR_10baseT = 0, XCVR_AUI, XCVR_10baseTOnly, XCVR_10base2, XCVR_100baseTx,
-	XCVR_100baseFx, XCVR_MII = 6, XCVR_Default = 8,
-};
-
-static struct media_table {
-	char *name;
-	unsigned int media_bits:16,	/* Bits to set in Wn4_Media register. */
-		mask:8,			/* The transceiver-present bit in Wn3_Config. */
-		next:8;			/* The media type to try next. */
-	short wait;			/* Time before we check media status. */
-} media_tbl[] = {
-	{ "10baseT", Media_10TP, 0x08, XCVR_10base2, (14 * HZ) / 10 },
-	{ "10Mbs AUI", Media_SQE, 0x20, XCVR_Default, (1 * HZ) / 10},
-	{ "undefined", 0, 0x80, XCVR_10baseT, 10000},
-	{ "10base2", 0, 0x10, XCVR_AUI, (1 * HZ) / 10},
-	{ "100baseTX", Media_Lnk, 0x02, XCVR_100baseFx, (14 * HZ) / 10},
-	{ "100baseFX", Media_Lnk, 0x04, XCVR_MII, (14 * HZ) / 10},
-	{ "MII", 0, 0x40, XCVR_10baseT, 3 * HZ},
-	{ "undefined", 0, 0x01, XCVR_10baseT, 10000},
-	{ "Default", 0, 0xFF, XCVR_10baseT, 10000},
-};
-
-#ifdef __ISAPNP__
-static struct isapnp_device_id corkscrew_isapnp_adapters[] = {
-	{	ISAPNP_ANY_ID, ISAPNP_ANY_ID,
-		ISAPNP_VENDOR('T', 'C', 'M'), ISAPNP_FUNCTION(0x5051),
-		(long) "3Com Fast EtherLink ISA" },
-	{ }	/* terminate list */
-};
-
-MODULE_DEVICE_TABLE(isapnp, corkscrew_isapnp_adapters);
-
-static int nopnp;
-#endif /* __ISAPNP__ */
-
-static struct net_device *corkscrew_scan(int unit);
-static int corkscrew_setup(struct net_device *dev, int ioaddr,
-			    struct pnp_dev *idev, int card_number);
-static int corkscrew_open(struct net_device *dev);
-static void corkscrew_timer(struct timer_list *t);
-static netdev_tx_t corkscrew_start_xmit(struct sk_buff *skb,
-					struct net_device *dev);
-static int corkscrew_rx(struct net_device *dev);
-static void corkscrew_timeout(struct net_device *dev, unsigned int txqueue);
-static int boomerang_rx(struct net_device *dev);
-static irqreturn_t corkscrew_interrupt(int irq, void *dev_id);
-static int corkscrew_close(struct net_device *dev);
-static void update_stats(int addr, struct net_device *dev);
-static struct net_device_stats *corkscrew_get_stats(struct net_device *dev);
-static void set_rx_mode(struct net_device *dev);
-static const struct ethtool_ops netdev_ethtool_ops;
-
-
-/*
-   Unfortunately maximizing the shared code between the integrated and
-   module version of the driver results in a complicated set of initialization
-   procedures.
-   init_module() -- modules /  tc59x_init()  -- built-in
-		The wrappers for corkscrew_scan()
-   corkscrew_scan()  		 The common routine that scans for PCI and EISA cards
-   corkscrew_found_device() Allocate a device structure when we find a card.
-					Different versions exist for modules and built-in.
-   corkscrew_probe1()		Fill in the device structure -- this is separated
-					so that the modules code can put it in dev->init.
-*/
-/* This driver uses 'options' to pass the media type, full-duplex flag, etc. */
-/* Note: this is the only limit on the number of cards supported!! */
-static int options[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1, };
-
-#ifdef MODULE
-static int debug = -1;
-
-module_param(debug, int, 0);
-module_param_array(options, int, NULL, 0);
-module_param(rx_copybreak, int, 0);
-module_param(max_interrupt_work, int, 0);
-MODULE_PARM_DESC(debug, "3c515 debug level (0-6)");
-MODULE_PARM_DESC(options, "3c515: Bits 0-2: media type, bit 3: full duplex, bit 4: bus mastering");
-MODULE_PARM_DESC(rx_copybreak, "3c515 copy breakpoint for copy-only-tiny-frames");
-MODULE_PARM_DESC(max_interrupt_work, "3c515 maximum events handled per interrupt");
-
-/* A list of all installed Vortex devices, for removing the driver module. */
-/* we will need locking (and refcounting) if we ever use it for more */
-static LIST_HEAD(root_corkscrew_dev);
-
-static int corkscrew_init_module(void)
-{
-	int found = 0;
-	if (debug >= 0)
-		corkscrew_debug = debug;
-	while (corkscrew_scan(-1))
-		found++;
-	return found ? 0 : -ENODEV;
-}
-module_init(corkscrew_init_module);
-
-#else
-struct net_device *tc515_probe(int unit)
-{
-	struct net_device *dev = corkscrew_scan(unit);
-
-	if (!dev)
-		return ERR_PTR(-ENODEV);
-
-	return dev;
-}
-#endif				/* not MODULE */
-
-static int check_device(unsigned ioaddr)
-{
-	int timer;
-
-	if (!request_region(ioaddr, CORKSCREW_TOTAL_SIZE, "3c515"))
-		return 0;
-	/* Check the resource configuration for a matching ioaddr. */
-	if ((inw(ioaddr + 0x2002) & 0x1f0) != (ioaddr & 0x1f0)) {
-		release_region(ioaddr, CORKSCREW_TOTAL_SIZE);
-		return 0;
-	}
-	/* Verify by reading the device ID from the EEPROM. */
-	outw(EEPROM_Read + 7, ioaddr + Wn0EepromCmd);
-	/* Pause for at least 162 us. for the read to take place. */
-	for (timer = 4; timer >= 0; timer--) {
-		udelay(162);
-		if ((inw(ioaddr + Wn0EepromCmd) & 0x0200) == 0)
-			break;
-	}
-	if (inw(ioaddr + Wn0EepromData) != 0x6d50) {
-		release_region(ioaddr, CORKSCREW_TOTAL_SIZE);
-		return 0;
-	}
-	return 1;
-}
-
-static void cleanup_card(struct net_device *dev)
-{
-	struct corkscrew_private *vp = netdev_priv(dev);
-	list_del_init(&vp->list);
-	if (dev->dma)
-		free_dma(dev->dma);
-	outw(TotalReset, dev->base_addr + EL3_CMD);
-	release_region(dev->base_addr, CORKSCREW_TOTAL_SIZE);
-	if (vp->dev)
-		pnp_device_detach(to_pnp_dev(vp->dev));
-}
-
-static struct net_device *corkscrew_scan(int unit)
-{
-	struct net_device *dev;
-	static int cards_found = 0;
-	static int ioaddr;
-	int err;
-#ifdef __ISAPNP__
-	short i;
-	static int pnp_cards;
-#endif
-
-	dev = alloc_etherdev(sizeof(struct corkscrew_private));
-	if (!dev)
-		return ERR_PTR(-ENOMEM);
-
-	if (unit >= 0) {
-		sprintf(dev->name, "eth%d", unit);
-		netdev_boot_setup_check(dev);
-	}
-
-#ifdef __ISAPNP__
-	if(nopnp == 1)
-		goto no_pnp;
-	for(i=0; corkscrew_isapnp_adapters[i].vendor != 0; i++) {
-		struct pnp_dev *idev = NULL;
-		int irq;
-		while((idev = pnp_find_dev(NULL,
-					   corkscrew_isapnp_adapters[i].vendor,
-					   corkscrew_isapnp_adapters[i].function,
-					   idev))) {
-
-			if (pnp_device_attach(idev) < 0)
-				continue;
-			if (pnp_activate_dev(idev) < 0) {
-				pr_warn("pnp activate failed (out of resources?)\n");
-				pnp_device_detach(idev);
-				continue;
-			}
-			if (!pnp_port_valid(idev, 0) || !pnp_irq_valid(idev, 0)) {
-				pnp_device_detach(idev);
-				continue;
-			}
-			ioaddr = pnp_port_start(idev, 0);
-			irq = pnp_irq(idev, 0);
-			if (!check_device(ioaddr)) {
-				pnp_device_detach(idev);
-				continue;
-			}
-			if(corkscrew_debug)
-				pr_debug("ISAPNP reports %s at i/o 0x%x, irq %d\n",
-					(char*) corkscrew_isapnp_adapters[i].driver_data, ioaddr, irq);
-			pr_info("3c515 Resource configuration register %#4.4x, DCR %4.4x.\n",
-		     		inl(ioaddr + 0x2002), inw(ioaddr + 0x2000));
-			/* irq = inw(ioaddr + 0x2002) & 15; */ /* Use the irq from isapnp */
-			SET_NETDEV_DEV(dev, &idev->dev);
-			pnp_cards++;
-			err = corkscrew_setup(dev, ioaddr, idev, cards_found++);
-			if (!err)
-				return dev;
-			cleanup_card(dev);
-		}
-	}
-no_pnp:
-#endif /* __ISAPNP__ */
-
-	/* Check all locations on the ISA bus -- evil! */
-	for (ioaddr = 0x100; ioaddr < 0x400; ioaddr += 0x20) {
-		if (!check_device(ioaddr))
-			continue;
-
-		pr_info("3c515 Resource configuration register %#4.4x, DCR %4.4x.\n",
-		     inl(ioaddr + 0x2002), inw(ioaddr + 0x2000));
-		err = corkscrew_setup(dev, ioaddr, NULL, cards_found++);
-		if (!err)
-			return dev;
-		cleanup_card(dev);
-	}
-	free_netdev(dev);
-	return NULL;
-}
-
-
-static const struct net_device_ops netdev_ops = {
-	.ndo_open		= corkscrew_open,
-	.ndo_stop		= corkscrew_close,
-	.ndo_start_xmit		= corkscrew_start_xmit,
-	.ndo_tx_timeout		= corkscrew_timeout,
-	.ndo_get_stats		= corkscrew_get_stats,
-	.ndo_set_rx_mode	= set_rx_mode,
-	.ndo_set_mac_address 	= eth_mac_addr,
-	.ndo_validate_addr	= eth_validate_addr,
-};
-
-
-static int corkscrew_setup(struct net_device *dev, int ioaddr,
-			    struct pnp_dev *idev, int card_number)
-{
-	struct corkscrew_private *vp = netdev_priv(dev);
-	unsigned int eeprom[0x40], checksum = 0;	/* EEPROM contents */
-	__be16 addr[ETH_ALEN / 2];
-	int i;
-	int irq;
-
-#ifdef __ISAPNP__
-	if (idev) {
-		irq = pnp_irq(idev, 0);
-		vp->dev = &idev->dev;
-	} else {
-		irq = inw(ioaddr + 0x2002) & 15;
-	}
-#else
-	irq = inw(ioaddr + 0x2002) & 15;
-#endif
-
-	dev->base_addr = ioaddr;
-	dev->irq = irq;
-	dev->dma = inw(ioaddr + 0x2000) & 7;
-	vp->product_name = "3c515";
-	vp->options = dev->mem_start;
-	vp->our_dev = dev;
-
-	if (!vp->options) {
-		 if (card_number >= MAX_UNITS)
-			vp->options = -1;
-		else
-			vp->options = options[card_number];
-	}
-
-	if (vp->options >= 0) {
-		vp->media_override = vp->options & 7;
-		if (vp->media_override == 2)
-			vp->media_override = 0;
-		vp->full_duplex = (vp->options & 8) ? 1 : 0;
-		vp->bus_master = (vp->options & 16) ? 1 : 0;
-	} else {
-		vp->media_override = 7;
-		vp->full_duplex = 0;
-		vp->bus_master = 0;
-	}
-#ifdef MODULE
-	list_add(&vp->list, &root_corkscrew_dev);
-#endif
-
-	pr_info("%s: 3Com %s at %#3x,", dev->name, vp->product_name, ioaddr);
-
-	spin_lock_init(&vp->lock);
-
-	timer_setup(&vp->timer, corkscrew_timer, 0);
-
-	/* Read the station address from the EEPROM. */
-	EL3WINDOW(0);
-	for (i = 0; i < 0x18; i++) {
-		int timer;
-		outw(EEPROM_Read + i, ioaddr + Wn0EepromCmd);
-		/* Pause for at least 162 us. for the read to take place. */
-		for (timer = 4; timer >= 0; timer--) {
-			udelay(162);
-			if ((inw(ioaddr + Wn0EepromCmd) & 0x0200) == 0)
-				break;
-		}
-		eeprom[i] = inw(ioaddr + Wn0EepromData);
-		checksum ^= eeprom[i];
-		if (i < 3)
-			addr[i] = htons(eeprom[i]);
-	}
-	eth_hw_addr_set(dev, (u8 *)addr);
-	checksum = (checksum ^ (checksum >> 8)) & 0xff;
-	if (checksum != 0x00)
-		pr_cont(" ***INVALID CHECKSUM %4.4x*** ", checksum);
-	pr_cont(" %pM", dev->dev_addr);
-	if (eeprom[16] == 0x11c7) {	/* Corkscrew */
-		if (request_dma(dev->dma, "3c515")) {
-			pr_cont(", DMA %d allocation failed", dev->dma);
-			dev->dma = 0;
-		} else
-			pr_cont(", DMA %d", dev->dma);
-	}
-	pr_cont(", IRQ %d\n", dev->irq);
-	/* Tell them about an invalid IRQ. */
-	if (corkscrew_debug && (dev->irq <= 0 || dev->irq > 15))
-		pr_warn(" *** Warning: this IRQ is unlikely to work! ***\n");
-
-	{
-		static const char * const ram_split[] = {
-			"5:3", "3:1", "1:1", "3:5"
-		};
-		__u32 config;
-		EL3WINDOW(3);
-		vp->available_media = inw(ioaddr + Wn3_Options);
-		config = inl(ioaddr + Wn3_Config);
-		if (corkscrew_debug > 1)
-			pr_info("  Internal config register is %4.4x, transceivers %#x.\n",
-				config, inw(ioaddr + Wn3_Options));
-		pr_info("  %dK %s-wide RAM %s Rx:Tx split, %s%s interface.\n",
-			8 << config & Ram_size,
-			config & Ram_width ? "word" : "byte",
-			ram_split[(config & Ram_split) >> Ram_split_shift],
-			config & Autoselect ? "autoselect/" : "",
-			media_tbl[(config & Xcvr) >> Xcvr_shift].name);
-		vp->default_media = (config & Xcvr) >> Xcvr_shift;
-		vp->autoselect = config & Autoselect ? 1 : 0;
-		dev->if_port = vp->default_media;
-	}
-	if (vp->media_override != 7) {
-		pr_info("  Media override to transceiver type %d (%s).\n",
-		       vp->media_override,
-		       media_tbl[vp->media_override].name);
-		dev->if_port = vp->media_override;
-	}
-
-	vp->capabilities = eeprom[16];
-	vp->full_bus_master_tx = (vp->capabilities & 0x20) ? 1 : 0;
-	/* Rx is broken at 10mbps, so we always disable it. */
-	/* vp->full_bus_master_rx = 0; */
-	vp->full_bus_master_rx = (vp->capabilities & 0x20) ? 1 : 0;
-
-	/* The 3c51x-specific entries in the device structure. */
-	dev->netdev_ops = &netdev_ops;
-	dev->watchdog_timeo = (400 * HZ) / 1000;
-	dev->ethtool_ops = &netdev_ethtool_ops;
-
-	return register_netdev(dev);
-}
-
-
-static int corkscrew_open(struct net_device *dev)
-{
-	int ioaddr = dev->base_addr;
-	struct corkscrew_private *vp = netdev_priv(dev);
-	bool armtimer = false;
-	__u32 config;
-	int i;
-
-	/* Before initializing select the active media port. */
-	EL3WINDOW(3);
-	if (vp->full_duplex)
-		outb(0x20, ioaddr + Wn3_MAC_Ctrl);	/* Set the full-duplex bit. */
-	config = inl(ioaddr + Wn3_Config);
-
-	if (vp->media_override != 7) {
-		if (corkscrew_debug > 1)
-			pr_info("%s: Media override to transceiver %d (%s).\n",
-				dev->name, vp->media_override,
-				media_tbl[vp->media_override].name);
-		dev->if_port = vp->media_override;
-	} else if (vp->autoselect) {
-		/* Find first available media type, starting with 100baseTx. */
-		dev->if_port = 4;
-		while (!(vp->available_media & media_tbl[dev->if_port].mask))
-			dev->if_port = media_tbl[dev->if_port].next;
-
-		if (corkscrew_debug > 1)
-			pr_debug("%s: Initial media type %s.\n",
-			       dev->name, media_tbl[dev->if_port].name);
-		armtimer = true;
-	} else
-		dev->if_port = vp->default_media;
-
-	config = (config & ~Xcvr) | (dev->if_port << Xcvr_shift);
-	outl(config, ioaddr + Wn3_Config);
-
-	if (corkscrew_debug > 1) {
-		pr_debug("%s: corkscrew_open() InternalConfig %8.8x.\n",
-		       dev->name, config);
-	}
-
-	outw(TxReset, ioaddr + EL3_CMD);
-	for (i = 20; i >= 0; i--)
-		if (!(inw(ioaddr + EL3_STATUS) & CmdInProgress))
-			break;
-
-	outw(RxReset, ioaddr + EL3_CMD);
-	/* Wait a few ticks for the RxReset command to complete. */
-	for (i = 20; i >= 0; i--)
-		if (!(inw(ioaddr + EL3_STATUS) & CmdInProgress))
-			break;
-
-	outw(SetStatusEnb | 0x00, ioaddr + EL3_CMD);
-
-	/* Use the now-standard shared IRQ implementation. */
-	if (vp->capabilities == 0x11c7) {
-		/* Corkscrew: Cannot share ISA resources. */
-		if (dev->irq == 0 ||
-		    dev->dma == 0 ||
-		    request_irq(dev->irq, corkscrew_interrupt, 0,
-				vp->product_name, dev))
-			return -EAGAIN;
-		enable_dma(dev->dma);
-		set_dma_mode(dev->dma, DMA_MODE_CASCADE);
-	} else if (request_irq(dev->irq, corkscrew_interrupt, IRQF_SHARED,
-			       vp->product_name, dev)) {
-		return -EAGAIN;
-	}
-
-	if (armtimer)
-		mod_timer(&vp->timer, jiffies + media_tbl[dev->if_port].wait);
-
-	if (corkscrew_debug > 1) {
-		EL3WINDOW(4);
-		pr_debug("%s: corkscrew_open() irq %d media status %4.4x.\n",
-		       dev->name, dev->irq, inw(ioaddr + Wn4_Media));
-	}
-
-	/* Set the station address and mask in window 2 each time opened. */
-	EL3WINDOW(2);
-	for (i = 0; i < 6; i++)
-		outb(dev->dev_addr[i], ioaddr + i);
-	for (; i < 12; i += 2)
-		outw(0, ioaddr + i);
-
-	if (dev->if_port == 3)
-		/* Start the thinnet transceiver. We should really wait 50ms... */
-		outw(StartCoax, ioaddr + EL3_CMD);
-	EL3WINDOW(4);
-	outw((inw(ioaddr + Wn4_Media) & ~(Media_10TP | Media_SQE)) |
-	     media_tbl[dev->if_port].media_bits, ioaddr + Wn4_Media);
-
-	/* Switch to the stats window, and clear all stats by reading. */
-	outw(StatsDisable, ioaddr + EL3_CMD);
-	EL3WINDOW(6);
-	for (i = 0; i < 10; i++)
-		inb(ioaddr + i);
-	inw(ioaddr + 10);
-	inw(ioaddr + 12);
-	/* New: On the Vortex we must also clear the BadSSD counter. */
-	EL3WINDOW(4);
-	inb(ioaddr + 12);
-	/* ..and on the Boomerang we enable the extra statistics bits. */
-	outw(0x0040, ioaddr + Wn4_NetDiag);
-
-	/* Switch to register set 7 for normal use. */
-	EL3WINDOW(7);
-
-	if (vp->full_bus_master_rx) {	/* Boomerang bus master. */
-		vp->cur_rx = vp->dirty_rx = 0;
-		if (corkscrew_debug > 2)
-			pr_debug("%s:  Filling in the Rx ring.\n", dev->name);
-		for (i = 0; i < RX_RING_SIZE; i++) {
-			struct sk_buff *skb;
-			if (i < (RX_RING_SIZE - 1))
-				vp->rx_ring[i].next =
-				    isa_virt_to_bus(&vp->rx_ring[i + 1]);
-			else
-				vp->rx_ring[i].next = 0;
-			vp->rx_ring[i].status = 0;	/* Clear complete bit. */
-			vp->rx_ring[i].length = PKT_BUF_SZ | 0x80000000;
-			skb = netdev_alloc_skb(dev, PKT_BUF_SZ);
-			vp->rx_skbuff[i] = skb;
-			if (skb == NULL)
-				break;	/* Bad news!  */
-			skb_reserve(skb, 2);	/* Align IP on 16 byte boundaries */
-			vp->rx_ring[i].addr = isa_virt_to_bus(skb->data);
-		}
-		if (i != 0)
-			vp->rx_ring[i - 1].next =
-				isa_virt_to_bus(&vp->rx_ring[0]);	/* Wrap the ring. */
-		outl(isa_virt_to_bus(&vp->rx_ring[0]), ioaddr + UpListPtr);
-	}
-	if (vp->full_bus_master_tx) {	/* Boomerang bus master Tx. */
-		vp->cur_tx = vp->dirty_tx = 0;
-		outb(PKT_BUF_SZ >> 8, ioaddr + TxFreeThreshold);	/* Room for a packet. */
-		/* Clear the Tx ring. */
-		for (i = 0; i < TX_RING_SIZE; i++)
-			vp->tx_skbuff[i] = NULL;
-		outl(0, ioaddr + DownListPtr);
-	}
-	/* Set receiver mode: presumably accept b-case and phys addr only. */
-	set_rx_mode(dev);
-	outw(StatsEnable, ioaddr + EL3_CMD);	/* Turn on statistics. */
-
-	netif_start_queue(dev);
-
-	outw(RxEnable, ioaddr + EL3_CMD);	/* Enable the receiver. */
-	outw(TxEnable, ioaddr + EL3_CMD);	/* Enable transmitter. */
-	/* Allow status bits to be seen. */
-	outw(SetStatusEnb | AdapterFailure | IntReq | StatsFull |
-	     (vp->full_bus_master_tx ? DownComplete : TxAvailable) |
-	     (vp->full_bus_master_rx ? UpComplete : RxComplete) |
-	     (vp->bus_master ? DMADone : 0), ioaddr + EL3_CMD);
-	/* Ack all pending events, and set active indicator mask. */
-	outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq,
-	     ioaddr + EL3_CMD);
-	outw(SetIntrEnb | IntLatch | TxAvailable | RxComplete | StatsFull
-	     | (vp->bus_master ? DMADone : 0) | UpComplete | DownComplete,
-	     ioaddr + EL3_CMD);
-
-	return 0;
-}
-
-static void corkscrew_timer(struct timer_list *t)
-{
-#ifdef AUTOMEDIA
-	struct corkscrew_private *vp = timer_container_of(vp, t, timer);
-	struct net_device *dev = vp->our_dev;
-	int ioaddr = dev->base_addr;
-	unsigned long flags;
-	int ok = 0;
-
-	if (corkscrew_debug > 1)
-		pr_debug("%s: Media selection timer tick happened, %s.\n",
-		       dev->name, media_tbl[dev->if_port].name);
-
-	spin_lock_irqsave(&vp->lock, flags);
-
-	{
-		int old_window = inw(ioaddr + EL3_CMD) >> 13;
-		int media_status;
-		EL3WINDOW(4);
-		media_status = inw(ioaddr + Wn4_Media);
-		switch (dev->if_port) {
-		case 0:
-		case 4:
-		case 5:	/* 10baseT, 100baseTX, 100baseFX  */
-			if (media_status & Media_LnkBeat) {
-				ok = 1;
-				if (corkscrew_debug > 1)
-					pr_debug("%s: Media %s has link beat, %x.\n",
-						dev->name,
-						media_tbl[dev->if_port].name,
-						media_status);
-			} else if (corkscrew_debug > 1)
-				pr_debug("%s: Media %s is has no link beat, %x.\n",
-					dev->name,
-					media_tbl[dev->if_port].name,
-					media_status);
-
-			break;
-		default:	/* Other media types handled by Tx timeouts. */
-			if (corkscrew_debug > 1)
-				pr_debug("%s: Media %s is has no indication, %x.\n",
-					dev->name,
-					media_tbl[dev->if_port].name,
-					media_status);
-			ok = 1;
-		}
-		if (!ok) {
-			__u32 config;
-
-			do {
-				dev->if_port =
-				    media_tbl[dev->if_port].next;
-			}
-			while (!(vp->available_media & media_tbl[dev->if_port].mask));
-
-			if (dev->if_port == 8) {	/* Go back to default. */
-				dev->if_port = vp->default_media;
-				if (corkscrew_debug > 1)
-					pr_debug("%s: Media selection failing, using default %s port.\n",
-						dev->name,
-						media_tbl[dev->if_port].name);
-			} else {
-				if (corkscrew_debug > 1)
-					pr_debug("%s: Media selection failed, now trying %s port.\n",
-						dev->name,
-						media_tbl[dev->if_port].name);
-				vp->timer.expires = jiffies + media_tbl[dev->if_port].wait;
-				add_timer(&vp->timer);
-			}
-			outw((media_status & ~(Media_10TP | Media_SQE)) |
-			     media_tbl[dev->if_port].media_bits,
-			     ioaddr + Wn4_Media);
-
-			EL3WINDOW(3);
-			config = inl(ioaddr + Wn3_Config);
-			config = (config & ~Xcvr) | (dev->if_port << Xcvr_shift);
-			outl(config, ioaddr + Wn3_Config);
-
-			outw(dev->if_port == 3 ? StartCoax : StopCoax,
-			     ioaddr + EL3_CMD);
-		}
-		EL3WINDOW(old_window);
-	}
-
-	spin_unlock_irqrestore(&vp->lock, flags);
-	if (corkscrew_debug > 1)
-		pr_debug("%s: Media selection timer finished, %s.\n",
-		       dev->name, media_tbl[dev->if_port].name);
-
-#endif				/* AUTOMEDIA */
-}
-
-static void corkscrew_timeout(struct net_device *dev, unsigned int txqueue)
-{
-	int i;
-	struct corkscrew_private *vp = netdev_priv(dev);
-	int ioaddr = dev->base_addr;
-
-	pr_warn("%s: transmit timed out, tx_status %2.2x status %4.4x\n",
-		dev->name, inb(ioaddr + TxStatus),
-		inw(ioaddr + EL3_STATUS));
-	/* Slight code bloat to be user friendly. */
-	if ((inb(ioaddr + TxStatus) & 0x88) == 0x88)
-		pr_warn("%s: Transmitter encountered 16 collisions -- network cable problem?\n",
-			dev->name);
-#ifndef final_version
-	pr_debug("  Flags; bus-master %d, full %d; dirty %d current %d.\n",
-	       vp->full_bus_master_tx, vp->tx_full, vp->dirty_tx,
-	       vp->cur_tx);
-	pr_debug("  Down list %8.8x vs. %p.\n", inl(ioaddr + DownListPtr),
-	       &vp->tx_ring[0]);
-	for (i = 0; i < TX_RING_SIZE; i++) {
-		pr_debug("  %d: %p  length %8.8x status %8.8x\n", i,
-		       &vp->tx_ring[i],
-		       vp->tx_ring[i].length, vp->tx_ring[i].status);
-	}
-#endif
-	/* Issue TX_RESET and TX_START commands. */
-	outw(TxReset, ioaddr + EL3_CMD);
-	for (i = 20; i >= 0; i--)
-		if (!(inw(ioaddr + EL3_STATUS) & CmdInProgress))
-			break;
-	outw(TxEnable, ioaddr + EL3_CMD);
-	netif_trans_update(dev); /* prevent tx timeout */
-	dev->stats.tx_errors++;
-	dev->stats.tx_dropped++;
-	netif_wake_queue(dev);
-}
-
-static netdev_tx_t corkscrew_start_xmit(struct sk_buff *skb,
-					struct net_device *dev)
-{
-	struct corkscrew_private *vp = netdev_priv(dev);
-	int ioaddr = dev->base_addr;
-
-	/* Block a timer-based transmit from overlapping. */
-
-	netif_stop_queue(dev);
-
-	if (vp->full_bus_master_tx) {	/* BOOMERANG bus-master */
-		/* Calculate the next Tx descriptor entry. */
-		int entry = vp->cur_tx % TX_RING_SIZE;
-		struct boom_tx_desc *prev_entry;
-		unsigned long flags;
-		int i;
-
-		if (vp->tx_full)	/* No room to transmit with */
-			return NETDEV_TX_BUSY;
-		if (vp->cur_tx != 0)
-			prev_entry = &vp->tx_ring[(vp->cur_tx - 1) % TX_RING_SIZE];
-		else
-			prev_entry = NULL;
-		if (corkscrew_debug > 3)
-			pr_debug("%s: Trying to send a packet, Tx index %d.\n",
-				dev->name, vp->cur_tx);
-		/* vp->tx_full = 1; */
-		vp->tx_skbuff[entry] = skb;
-		vp->tx_ring[entry].next = 0;
-		vp->tx_ring[entry].addr = isa_virt_to_bus(skb->data);
-		vp->tx_ring[entry].length = skb->len | 0x80000000;
-		vp->tx_ring[entry].status = skb->len | 0x80000000;
-
-		spin_lock_irqsave(&vp->lock, flags);
-		outw(DownStall, ioaddr + EL3_CMD);
-		/* Wait for the stall to complete. */
-		for (i = 20; i >= 0; i--)
-			if ((inw(ioaddr + EL3_STATUS) & CmdInProgress) == 0)
-				break;
-		if (prev_entry)
-			prev_entry->next = isa_virt_to_bus(&vp->tx_ring[entry]);
-		if (inl(ioaddr + DownListPtr) == 0) {
-			outl(isa_virt_to_bus(&vp->tx_ring[entry]),
-			     ioaddr + DownListPtr);
-			queued_packet++;
-		}
-		outw(DownUnstall, ioaddr + EL3_CMD);
-		spin_unlock_irqrestore(&vp->lock, flags);
-
-		vp->cur_tx++;
-		if (vp->cur_tx - vp->dirty_tx > TX_RING_SIZE - 1)
-			vp->tx_full = 1;
-		else {		/* Clear previous interrupt enable. */
-			if (prev_entry)
-				prev_entry->status &= ~0x80000000;
-			netif_wake_queue(dev);
-		}
-		return NETDEV_TX_OK;
-	}
-	/* Put out the doubleword header... */
-	outl(skb->len, ioaddr + TX_FIFO);
-	dev->stats.tx_bytes += skb->len;
-#ifdef VORTEX_BUS_MASTER
-	if (vp->bus_master) {
-		/* Set the bus-master controller to transfer the packet. */
-		outl(isa_virt_to_bus(skb->data), ioaddr + Wn7_MasterAddr);
-		outw((skb->len + 3) & ~3, ioaddr + Wn7_MasterLen);
-		vp->tx_skb = skb;
-		outw(StartDMADown, ioaddr + EL3_CMD);
-		/* queue will be woken at the DMADone interrupt. */
-	} else {
-		/* ... and the packet rounded to a doubleword. */
-		outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
-		dev_kfree_skb(skb);
-		if (inw(ioaddr + TxFree) > 1536) {
-			netif_wake_queue(dev);
-		} else
-			/* Interrupt us when the FIFO has room for max-sized packet. */
-			outw(SetTxThreshold + (1536 >> 2),
-			     ioaddr + EL3_CMD);
-	}
-#else
-	/* ... and the packet rounded to a doubleword. */
-	outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
-	dev_kfree_skb(skb);
-	if (inw(ioaddr + TxFree) > 1536) {
-		netif_wake_queue(dev);
-	} else
-		/* Interrupt us when the FIFO has room for max-sized packet. */
-		outw(SetTxThreshold + (1536 >> 2), ioaddr + EL3_CMD);
-#endif				/* bus master */
-
-
-	/* Clear the Tx status stack. */
-	{
-		short tx_status;
-		int i = 4;
-
-		while (--i > 0 && (tx_status = inb(ioaddr + TxStatus)) > 0) {
-			if (tx_status & 0x3C) {	/* A Tx-disabling error occurred.  */
-				if (corkscrew_debug > 2)
-					pr_debug("%s: Tx error, status %2.2x.\n",
-						dev->name, tx_status);
-				if (tx_status & 0x04)
-					dev->stats.tx_fifo_errors++;
-				if (tx_status & 0x38)
-					dev->stats.tx_aborted_errors++;
-				if (tx_status & 0x30) {
-					int j;
-					outw(TxReset, ioaddr + EL3_CMD);
-					for (j = 20; j >= 0; j--)
-						if (!(inw(ioaddr + EL3_STATUS) & CmdInProgress))
-							break;
-				}
-				outw(TxEnable, ioaddr + EL3_CMD);
-			}
-			outb(0x00, ioaddr + TxStatus);	/* Pop the status stack. */
-		}
-	}
-	return NETDEV_TX_OK;
-}
-
-/* The interrupt handler does all of the Rx thread work and cleans up
-   after the Tx thread. */
-
-static irqreturn_t corkscrew_interrupt(int irq, void *dev_id)
-{
-	/* Use the now-standard shared IRQ implementation. */
-	struct net_device *dev = dev_id;
-	struct corkscrew_private *lp = netdev_priv(dev);
-	int ioaddr, status;
-	int latency;
-	int i = max_interrupt_work;
-
-	ioaddr = dev->base_addr;
-	latency = inb(ioaddr + Timer);
-
-	spin_lock(&lp->lock);
-
-	status = inw(ioaddr + EL3_STATUS);
-
-	if (corkscrew_debug > 4)
-		pr_debug("%s: interrupt, status %4.4x, timer %d.\n",
-			dev->name, status, latency);
-	if ((status & 0xE000) != 0xE000) {
-		static int donedidthis;
-		/* Some interrupt controllers store a bogus interrupt from boot-time.
-		   Ignore a single early interrupt, but don't hang the machine for
-		   other interrupt problems. */
-		if (donedidthis++ > 100) {
-			pr_err("%s: Bogus interrupt, bailing. Status %4.4x, start=%d.\n",
-				   dev->name, status, netif_running(dev));
-			free_irq(dev->irq, dev);
-			dev->irq = -1;
-		}
-	}
-
-	do {
-		if (corkscrew_debug > 5)
-			pr_debug("%s: In interrupt loop, status %4.4x.\n",
-			       dev->name, status);
-		if (status & RxComplete)
-			corkscrew_rx(dev);
-
-		if (status & TxAvailable) {
-			if (corkscrew_debug > 5)
-				pr_debug("	TX room bit was handled.\n");
-			/* There's room in the FIFO for a full-sized packet. */
-			outw(AckIntr | TxAvailable, ioaddr + EL3_CMD);
-			netif_wake_queue(dev);
-		}
-		if (status & DownComplete) {
-			unsigned int dirty_tx = lp->dirty_tx;
-
-			while (lp->cur_tx - dirty_tx > 0) {
-				int entry = dirty_tx % TX_RING_SIZE;
-				if (inl(ioaddr + DownListPtr) == isa_virt_to_bus(&lp->tx_ring[entry]))
-					break;	/* It still hasn't been processed. */
-				if (lp->tx_skbuff[entry]) {
-					dev_consume_skb_irq(lp->tx_skbuff[entry]);
-					lp->tx_skbuff[entry] = NULL;
-				}
-				dirty_tx++;
-			}
-			lp->dirty_tx = dirty_tx;
-			outw(AckIntr | DownComplete, ioaddr + EL3_CMD);
-			if (lp->tx_full && (lp->cur_tx - dirty_tx <= TX_RING_SIZE - 1)) {
-				lp->tx_full = 0;
-				netif_wake_queue(dev);
-			}
-		}
-#ifdef VORTEX_BUS_MASTER
-		if (status & DMADone) {
-			outw(0x1000, ioaddr + Wn7_MasterStatus);	/* Ack the event. */
-			dev_consume_skb_irq(lp->tx_skb);	/* Release the transferred buffer */
-			netif_wake_queue(dev);
-		}
-#endif
-		if (status & UpComplete) {
-			boomerang_rx(dev);
-			outw(AckIntr | UpComplete, ioaddr + EL3_CMD);
-		}
-		if (status & (AdapterFailure | RxEarly | StatsFull)) {
-			/* Handle all uncommon interrupts at once. */
-			if (status & RxEarly) {	/* Rx early is unused. */
-				corkscrew_rx(dev);
-				outw(AckIntr | RxEarly, ioaddr + EL3_CMD);
-			}
-			if (status & StatsFull) {	/* Empty statistics. */
-				static int DoneDidThat;
-				if (corkscrew_debug > 4)
-					pr_debug("%s: Updating stats.\n", dev->name);
-				update_stats(ioaddr, dev);
-				/* DEBUG HACK: Disable statistics as an interrupt source. */
-				/* This occurs when we have the wrong media type! */
-				if (DoneDidThat == 0 && inw(ioaddr + EL3_STATUS) & StatsFull) {
-					int win, reg;
-					pr_notice("%s: Updating stats failed, disabling stats as an interrupt source.\n",
-						dev->name);
-					for (win = 0; win < 8; win++) {
-						EL3WINDOW(win);
-						pr_notice("Vortex window %d:", win);
-						for (reg = 0; reg < 16; reg++)
-							pr_cont(" %2.2x", inb(ioaddr + reg));
-						pr_cont("\n");
-					}
-					EL3WINDOW(7);
-					outw(SetIntrEnb | TxAvailable |
-					     RxComplete | AdapterFailure |
-					     UpComplete | DownComplete |
-					     TxComplete, ioaddr + EL3_CMD);
-					DoneDidThat++;
-				}
-			}
-			if (status & AdapterFailure) {
-				/* Adapter failure requires Rx reset and reinit. */
-				outw(RxReset, ioaddr + EL3_CMD);
-				/* Set the Rx filter to the current state. */
-				set_rx_mode(dev);
-				outw(RxEnable, ioaddr + EL3_CMD);	/* Re-enable the receiver. */
-				outw(AckIntr | AdapterFailure,
-				     ioaddr + EL3_CMD);
-			}
-		}
-
-		if (--i < 0) {
-			pr_err("%s: Too much work in interrupt, status %4.4x. Disabling functions (%4.4x).\n",
-				dev->name, status, SetStatusEnb | ((~status) & 0x7FE));
-			/* Disable all pending interrupts. */
-			outw(SetStatusEnb | ((~status) & 0x7FE), ioaddr + EL3_CMD);
-			outw(AckIntr | 0x7FF, ioaddr + EL3_CMD);
-			break;
-		}
-		/* Acknowledge the IRQ. */
-		outw(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD);
-
-	} while ((status = inw(ioaddr + EL3_STATUS)) & (IntLatch | RxComplete));
-
-	spin_unlock(&lp->lock);
-
-	if (corkscrew_debug > 4)
-		pr_debug("%s: exiting interrupt, status %4.4x.\n", dev->name, status);
-	return IRQ_HANDLED;
-}
-
-static int corkscrew_rx(struct net_device *dev)
-{
-	int ioaddr = dev->base_addr;
-	int i;
-	short rx_status;
-
-	if (corkscrew_debug > 5)
-		pr_debug("   In rx_packet(), status %4.4x, rx_status %4.4x.\n",
-		     inw(ioaddr + EL3_STATUS), inw(ioaddr + RxStatus));
-	while ((rx_status = inw(ioaddr + RxStatus)) > 0) {
-		if (rx_status & 0x4000) {	/* Error, update stats. */
-			unsigned char rx_error = inb(ioaddr + RxErrors);
-			if (corkscrew_debug > 2)
-				pr_debug(" Rx error: status %2.2x.\n",
-				       rx_error);
-			dev->stats.rx_errors++;
-			if (rx_error & 0x01)
-				dev->stats.rx_over_errors++;
-			if (rx_error & 0x02)
-				dev->stats.rx_length_errors++;
-			if (rx_error & 0x04)
-				dev->stats.rx_frame_errors++;
-			if (rx_error & 0x08)
-				dev->stats.rx_crc_errors++;
-			if (rx_error & 0x10)
-				dev->stats.rx_length_errors++;
-		} else {
-			/* The packet length: up to 4.5K!. */
-			short pkt_len = rx_status & 0x1fff;
-			struct sk_buff *skb;
-
-			skb = netdev_alloc_skb(dev, pkt_len + 5 + 2);
-			if (corkscrew_debug > 4)
-				pr_debug("Receiving packet size %d status %4.4x.\n",
-				     pkt_len, rx_status);
-			if (skb != NULL) {
-				skb_reserve(skb, 2);	/* Align IP on 16 byte boundaries */
-				/* 'skb_put()' points to the start of sk_buff data area. */
-				insl(ioaddr + RX_FIFO,
-				     skb_put(skb, pkt_len),
-				     (pkt_len + 3) >> 2);
-				outw(RxDiscard, ioaddr + EL3_CMD);	/* Pop top Rx packet. */
-				skb->protocol = eth_type_trans(skb, dev);
-				netif_rx(skb);
-				dev->stats.rx_packets++;
-				dev->stats.rx_bytes += pkt_len;
-				/* Wait a limited time to go to next packet. */
-				for (i = 200; i >= 0; i--)
-					if (! (inw(ioaddr + EL3_STATUS) & CmdInProgress))
-						break;
-				continue;
-			} else if (corkscrew_debug)
-				pr_debug("%s: Couldn't allocate a sk_buff of size %d.\n", dev->name, pkt_len);
-		}
-		outw(RxDiscard, ioaddr + EL3_CMD);
-		dev->stats.rx_dropped++;
-		/* Wait a limited time to skip this packet. */
-		for (i = 200; i >= 0; i--)
-			if (!(inw(ioaddr + EL3_STATUS) & CmdInProgress))
-				break;
-	}
-	return 0;
-}
-
-static int boomerang_rx(struct net_device *dev)
-{
-	struct corkscrew_private *vp = netdev_priv(dev);
-	int entry = vp->cur_rx % RX_RING_SIZE;
-	int ioaddr = dev->base_addr;
-	int rx_status;
-
-	if (corkscrew_debug > 5)
-		pr_debug("   In boomerang_rx(), status %4.4x, rx_status %4.4x.\n",
-			inw(ioaddr + EL3_STATUS), inw(ioaddr + RxStatus));
-	while ((rx_status = vp->rx_ring[entry].status) & RxDComplete) {
-		if (rx_status & RxDError) {	/* Error, update stats. */
-			unsigned char rx_error = rx_status >> 16;
-			if (corkscrew_debug > 2)
-				pr_debug(" Rx error: status %2.2x.\n",
-				       rx_error);
-			dev->stats.rx_errors++;
-			if (rx_error & 0x01)
-				dev->stats.rx_over_errors++;
-			if (rx_error & 0x02)
-				dev->stats.rx_length_errors++;
-			if (rx_error & 0x04)
-				dev->stats.rx_frame_errors++;
-			if (rx_error & 0x08)
-				dev->stats.rx_crc_errors++;
-			if (rx_error & 0x10)
-				dev->stats.rx_length_errors++;
-		} else {
-			/* The packet length: up to 4.5K!. */
-			short pkt_len = rx_status & 0x1fff;
-			struct sk_buff *skb;
-
-			dev->stats.rx_bytes += pkt_len;
-			if (corkscrew_debug > 4)
-				pr_debug("Receiving packet size %d status %4.4x.\n",
-				     pkt_len, rx_status);
-
-			/* Check if the packet is long enough to just accept without
-			   copying to a properly sized skbuff. */
-			if (pkt_len < rx_copybreak &&
-			    (skb = netdev_alloc_skb(dev, pkt_len + 4)) != NULL) {
-				skb_reserve(skb, 2);	/* Align IP on 16 byte boundaries */
-				/* 'skb_put()' points to the start of sk_buff data area. */
-				skb_put_data(skb,
-					     isa_bus_to_virt(vp->rx_ring[entry].addr),
-					     pkt_len);
-				rx_copy++;
-			} else {
-				void *temp;
-				/* Pass up the skbuff already on the Rx ring. */
-				skb = vp->rx_skbuff[entry];
-				vp->rx_skbuff[entry] = NULL;
-				temp = skb_put(skb, pkt_len);
-				/* Remove this checking code for final release. */
-				if (isa_bus_to_virt(vp->rx_ring[entry].addr) != temp)
-					pr_warn("%s: Warning -- the skbuff addresses do not match in boomerang_rx: %p vs. %p / %p\n",
-						dev->name,
-						isa_bus_to_virt(vp->rx_ring[entry].addr),
-						skb->head, temp);
-				rx_nocopy++;
-			}
-			skb->protocol = eth_type_trans(skb, dev);
-			netif_rx(skb);
-			dev->stats.rx_packets++;
-		}
-		entry = (++vp->cur_rx) % RX_RING_SIZE;
-	}
-	/* Refill the Rx ring buffers. */
-	for (; vp->cur_rx - vp->dirty_rx > 0; vp->dirty_rx++) {
-		struct sk_buff *skb;
-		entry = vp->dirty_rx % RX_RING_SIZE;
-		if (vp->rx_skbuff[entry] == NULL) {
-			skb = netdev_alloc_skb(dev, PKT_BUF_SZ);
-			if (skb == NULL)
-				break;	/* Bad news!  */
-			skb_reserve(skb, 2);	/* Align IP on 16 byte boundaries */
-			vp->rx_ring[entry].addr = isa_virt_to_bus(skb->data);
-			vp->rx_skbuff[entry] = skb;
-		}
-		vp->rx_ring[entry].status = 0;	/* Clear complete bit. */
-	}
-	return 0;
-}
-
-static int corkscrew_close(struct net_device *dev)
-{
-	struct corkscrew_private *vp = netdev_priv(dev);
-	int ioaddr = dev->base_addr;
-	int i;
-
-	netif_stop_queue(dev);
-
-	if (corkscrew_debug > 1) {
-		pr_debug("%s: corkscrew_close() status %4.4x, Tx status %2.2x.\n",
-		     dev->name, inw(ioaddr + EL3_STATUS),
-		     inb(ioaddr + TxStatus));
-		pr_debug("%s: corkscrew close stats: rx_nocopy %d rx_copy %d tx_queued %d.\n",
-			dev->name, rx_nocopy, rx_copy, queued_packet);
-	}
-
-	timer_delete_sync(&vp->timer);
-
-	/* Turn off statistics ASAP.  We update lp->stats below. */
-	outw(StatsDisable, ioaddr + EL3_CMD);
-
-	/* Disable the receiver and transmitter. */
-	outw(RxDisable, ioaddr + EL3_CMD);
-	outw(TxDisable, ioaddr + EL3_CMD);
-
-	if (dev->if_port == XCVR_10base2)
-		/* Turn off thinnet power.  Green! */
-		outw(StopCoax, ioaddr + EL3_CMD);
-
-	free_irq(dev->irq, dev);
-
-	outw(SetIntrEnb | 0x0000, ioaddr + EL3_CMD);
-
-	update_stats(ioaddr, dev);
-	if (vp->full_bus_master_rx) {	/* Free Boomerang bus master Rx buffers. */
-		outl(0, ioaddr + UpListPtr);
-		for (i = 0; i < RX_RING_SIZE; i++)
-			if (vp->rx_skbuff[i]) {
-				dev_kfree_skb(vp->rx_skbuff[i]);
-				vp->rx_skbuff[i] = NULL;
-			}
-	}
-	if (vp->full_bus_master_tx) {	/* Free Boomerang bus master Tx buffers. */
-		outl(0, ioaddr + DownListPtr);
-		for (i = 0; i < TX_RING_SIZE; i++)
-			if (vp->tx_skbuff[i]) {
-				dev_kfree_skb(vp->tx_skbuff[i]);
-				vp->tx_skbuff[i] = NULL;
-			}
-	}
-
-	return 0;
-}
-
-static struct net_device_stats *corkscrew_get_stats(struct net_device *dev)
-{
-	struct corkscrew_private *vp = netdev_priv(dev);
-	unsigned long flags;
-
-	if (netif_running(dev)) {
-		spin_lock_irqsave(&vp->lock, flags);
-		update_stats(dev->base_addr, dev);
-		spin_unlock_irqrestore(&vp->lock, flags);
-	}
-	return &dev->stats;
-}
-
-/*  Update statistics.
-	Unlike with the EL3 we need not worry about interrupts changing
-	the window setting from underneath us, but we must still guard
-	against a race condition with a StatsUpdate interrupt updating the
-	table.  This is done by checking that the ASM (!) code generated uses
-	atomic updates with '+='.
-	*/
-static void update_stats(int ioaddr, struct net_device *dev)
-{
-	/* Unlike the 3c5x9 we need not turn off stats updates while reading. */
-	/* Switch to the stats window, and read everything. */
-	EL3WINDOW(6);
-	dev->stats.tx_carrier_errors += inb(ioaddr + 0);
-	dev->stats.tx_heartbeat_errors += inb(ioaddr + 1);
-	/* Multiple collisions. */ inb(ioaddr + 2);
-	dev->stats.collisions += inb(ioaddr + 3);
-	dev->stats.tx_window_errors += inb(ioaddr + 4);
-	dev->stats.rx_fifo_errors += inb(ioaddr + 5);
-	dev->stats.tx_packets += inb(ioaddr + 6);
-	dev->stats.tx_packets += (inb(ioaddr + 9) & 0x30) << 4;
-						/* Rx packets   */ inb(ioaddr + 7);
-						/* Must read to clear */
-	/* Tx deferrals */ inb(ioaddr + 8);
-	/* Don't bother with register 9, an extension of registers 6&7.
-	   If we do use the 6&7 values the atomic update assumption above
-	   is invalid. */
-	inw(ioaddr + 10);	/* Total Rx and Tx octets. */
-	inw(ioaddr + 12);
-	/* New: On the Vortex we must also clear the BadSSD counter. */
-	EL3WINDOW(4);
-	inb(ioaddr + 12);
-
-	/* We change back to window 7 (not 1) with the Vortex. */
-	EL3WINDOW(7);
-}
-
-/* This new version of set_rx_mode() supports v1.4 kernels.
-   The Vortex chip has no documented multicast filter, so the only
-   multicast setting is to receive all multicast frames.  At least
-   the chip has a very clean way to set the mode, unlike many others. */
-static void set_rx_mode(struct net_device *dev)
-{
-	int ioaddr = dev->base_addr;
-	unsigned short new_mode;
-
-	if (dev->flags & IFF_PROMISC) {
-		if (corkscrew_debug > 3)
-			pr_debug("%s: Setting promiscuous mode.\n",
-			       dev->name);
-		new_mode = SetRxFilter | RxStation | RxMulticast | RxBroadcast | RxProm;
-	} else if (!netdev_mc_empty(dev) || dev->flags & IFF_ALLMULTI) {
-		new_mode = SetRxFilter | RxStation | RxMulticast | RxBroadcast;
-	} else
-		new_mode = SetRxFilter | RxStation | RxBroadcast;
-
-	outw(new_mode, ioaddr + EL3_CMD);
-}
-
-static void netdev_get_drvinfo(struct net_device *dev,
-			       struct ethtool_drvinfo *info)
-{
-	strscpy(info->driver, DRV_NAME, sizeof(info->driver));
-	snprintf(info->bus_info, sizeof(info->bus_info), "ISA 0x%lx",
-		 dev->base_addr);
-}
-
-static u32 netdev_get_msglevel(struct net_device *dev)
-{
-	return corkscrew_debug;
-}
-
-static void netdev_set_msglevel(struct net_device *dev, u32 level)
-{
-	corkscrew_debug = level;
-}
-
-static const struct ethtool_ops netdev_ethtool_ops = {
-	.get_drvinfo		= netdev_get_drvinfo,
-	.get_msglevel		= netdev_get_msglevel,
-	.set_msglevel		= netdev_set_msglevel,
-};
-
-#ifdef MODULE
-static void __exit corkscrew_exit_module(void)
-{
-	while (!list_empty(&root_corkscrew_dev)) {
-		struct net_device *dev;
-		struct corkscrew_private *vp;
-
-		vp = list_entry(root_corkscrew_dev.next,
-				struct corkscrew_private, list);
-		dev = vp->our_dev;
-		unregister_netdev(dev);
-		cleanup_card(dev);
-		free_netdev(dev);
-	}
-}
-module_exit(corkscrew_exit_module);
-#endif				/* MODULE */
diff --git a/drivers/net/ethernet/3com/Kconfig b/drivers/net/ethernet/3com/Kconfig
index c05a1b63c1c9..3fd3202d9776 100644
--- a/drivers/net/ethernet/3com/Kconfig
+++ b/drivers/net/ethernet/3com/Kconfig
@@ -17,17 +17,6 @@ config NET_VENDOR_3COM
 
 if NET_VENDOR_3COM
 
-config 3C515
-	tristate "3c515 ISA \"Fast EtherLink\""
-	depends on ISA && ISA_DMA_API && !PPC32
-	select NETDEV_LEGACY_INIT
-	help
-	  If you have a 3Com ISA EtherLink XL "Corkscrew" 3c515 Fast Ethernet
-	  network card, say Y here.
-
-	  To compile this driver as a module, choose M here. The module
-	  will be called 3c515.
-
 config PCMCIA_3C574
 	tristate "3Com 3c574 PCMCIA support"
 	depends on PCMCIA && HAS_IOPORT
diff --git a/drivers/net/ethernet/3com/Makefile b/drivers/net/ethernet/3com/Makefile
index f7623fa2d441..babfd93d5d53 100644
--- a/drivers/net/ethernet/3com/Makefile
+++ b/drivers/net/ethernet/3com/Makefile
@@ -3,7 +3,6 @@
 # Makefile for the 3Com Ethernet device drivers
 #
 
-obj-$(CONFIG_3C515) += 3c515.o
 obj-$(CONFIG_PCMCIA_3C589) += 3c589_cs.o
 obj-$(CONFIG_PCMCIA_3C574) += 3c574_cs.o
 obj-$(CONFIG_VORTEX) += 3c59x.o

-- 
2.53.0


^ permalink raw reply related


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