From f1798e7443d4f2d574edd09048c9a88081bf3a7b Mon Sep 17 00:00:00 2001 From: Nexoniarz Date: Thu, 22 Oct 2026 09:23:34 +0200 Subject: [PATCH] rtl8139: let go of the device when asked The kernel's rtl8139 driver had no release hook, so /dev/pci refused every request for the card ("the kernel would not release it") and a hosted 8139too could never run on a machine where this driver probed first. release() follows e1000_release(): silence the chip before unhooking the interrupt, reset it and clear bus mastering so it stops writing into its buffers, take the interface out of the stack, then give the DMA buffers back. Tested in QEMU: ldlsd takes the card from the kernel, 8139too probes it, DHCP binds ldls0, and ping 10.9.0.2 gets 3 of 3 replies. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01HH7xukt4aaiGj1nQEAoQf1 --- kernel/drivers/net/rtl8139/rtl8139.c | 63 ++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/kernel/drivers/net/rtl8139/rtl8139.c b/kernel/drivers/net/rtl8139/rtl8139.c index 4249f61..bdcecde 100644 --- a/kernel/drivers/net/rtl8139/rtl8139.c +++ b/kernel/drivers/net/rtl8139/rtl8139.c @@ -370,6 +370,68 @@ rtl8139_probe(struct pci_dev *d) return 0; } +// Let go of the device, so another driver can have it. +// +// Without this the kernel's answer to "may I have the 8139" was always no, and +// a hosted driver for it could never run on a machine where this one had +// probed first -- which is every machine with one: +// +// found 10ec:8139 at 00:04.0, held by rtl8139 +// the kernel would not release it +// +// The order is the one e1000_release() follows and for the same reasons. The +// chip is silenced *before* the handler goes, because a level-triggered line +// left asserted with nobody to clear it is an interrupt storm. Then it is +// reset, which stops the receiver writing into a buffer that is about to be +// freed, and bus mastering is cleared so that nothing it still has queued can +// reach memory. Only then are the buffers given back: the arena will hand them +// to the next driver, and a chip still pointed at them would be writing frames +// into somebody else's descriptors. +static int +rtl8139_release(struct pci_dev *d) +{ + struct rtl8139 *r = 0; + + for (int i = 0; i < RTL8139_MAX_NICS; i++) + if (nics[i].pdev == d) { r = &nics[i]; break; } + + if (!r || !r->ready) + return 0; // never came up, or already let go + + acquire(&r->lock); + r->ready = 0; // transmit and receive refuse from here on + wr16(r, R_IMR, 0); // no more interrupts from it + wr16(r, R_ISR, 0xFFFF); // and none left pending + wr8(r, R_CR, 0); // receiver and transmitter off + release(&r->lock); + + if (d->irq != 0xFF && d->irq < 24) + irq_unregister(d->irq, rtl8139_intr, r); + + // Reset, and wait for it, so the chip has truly stopped before its buffers + // are reused. The reset bit clears itself when the chip is done. + wr8(r, R_CR, CR_RST); + for (int i = 0; i < 10000 && (rd8(r, R_CR) & CR_RST); i++) + microdelay(10); + pci_disable(d, PCI_CMD_BUS_MASTER); + + // Out of the stack, for the reason e1000_release() spells out: an interface + // left behind keeps its address and its route, and the stack goes on sending + // into a driver that now refuses every frame. + if (r->ndev) + net_detach(r->ndev); + + dma_free(r->rxbuf, RXBUF_TOTAL); + dma_free(r->txbuf, NTX * TXBUF); + r->rxbuf = r->txbuf = 0; + r->tx_slot = 0; + r->tx_packets = 0; + r->rx_packets = 0; + + cprintf("rtl8139: released; the interface is down\n"); + return 0; +} + static void rtl8139_attached(struct pci_dev *d, struct device *dev) { @@ -400,4 +462,5 @@ const struct pci_driver rtl8139_driver = { .ops = &rtl8139_netdev_ops, .probe = rtl8139_probe, .attached = rtl8139_attached, + .release = rtl8139_release, };