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, };