DORMANTno replies

[PATCH 2.4.25] pcnet32.c add .remove to pci_driver

From: Don Fry <hidden>
Date: 2004-02-21 00:56:57

Adds .remove function in pci_device structure.  Tested in IA32.

The driver has also been checked to comply with PCMCIA/cardbus remove
requirements, but as I don't have a PCMCIA card, it is untested.
If a PCMCIA card is removed, reads will return FFFF.  The FFFF will
cause all while loops to exit.
--- linux-2.4.25/drivers/net/mii.pcnet32.c	Fri Feb 20 16:26:20 2004
+++ linux-2.4.25/drivers/net/pcnet32.c	Fri Feb 20 16:51:42 2004
@@ -917,8 +917,12 @@
     dev->tx_timeout = pcnet32_tx_timeout;
     dev->watchdog_timeo = (5*HZ);
 
-    lp->next = pcnet32_dev;
-    pcnet32_dev = dev;
+    if (pdev) {
+	pci_set_drvdata(pdev, dev);
+    } else {
+	lp->next = pcnet32_dev;
+	pcnet32_dev = dev;
+    }
 
     /* Fill in the generic fields of the device structure. */
     register_netdev(dev);
@@ -1303,6 +1307,9 @@
     
     rap = lp->a.read_rap(ioaddr);
     while ((csr0 = lp->a.read_csr (ioaddr, 0)) & 0x8600 && --boguscnt >= 0) {
+	if (csr0 == 0xffff) {
+	    break;			/* PCMCIA remove happened */
+	}
 	/* Acknowledge all of the current interrupt sources ASAP. */
 	lp->a.write_csr (ioaddr, 0, csr0 & ~0x004f);
 
@@ -1720,9 +1727,25 @@
     return rc;
 }
 
+static void __devexit pcnet32_remove_one(struct pci_dev *pdev)
+{
+    struct net_device *dev = pci_get_drvdata(pdev);
+
+    if (dev) {
+	struct pcnet32_private *lp = dev->priv;
+
+	unregister_netdev(dev);
+	release_region(dev->base_addr, PCNET32_TOTAL_SIZE);
+	pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr);
+	free_netdev(dev);
+	pci_set_drvdata(pdev, NULL);
+    }
+}
+
 static struct pci_driver pcnet32_driver = {
     .name	= DRV_NAME,
     .probe	= pcnet32_probe_pci,
+    .remove	= __devexit_p(pcnet32_remove_one),
     .id_table	= pcnet32_pci_tbl,
 };
 
-- 
Don Fry
brazilnut@us.ibm.com
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help