]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] e100 deadlock fix
authorAndrew Morton <akpm@osdl.org>
Mon, 29 Nov 2004 05:38:30 +0000 (21:38 -0800)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Mon, 29 Nov 2004 05:38:30 +0000 (21:38 -0800)
Revert my version of this fix and apply Scott's version, which was acked by
the e100 maintainers.

Also, initialise the spinlocks before calling e100_hw_reset(), so things don't
instantly deadlock on SMP.

Signed-off-by: Scott Feldman <sfeldma@pobox.com>
Cc: Jeff Garzik <jgarzik@pobox.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
drivers/net/e100.c

index af78c85f11d9887aaf2e7686277741c8bf9f7f3c..c075355aabbba353be45c1acf67be415b1876230 100644 (file)
@@ -2204,33 +2204,38 @@ static int __devinit e100_probe(struct pci_dev *pdev,
                goto err_out_disable_pdev;
        }
 
-       nic->csr = ioremap(pci_resource_start(pdev, 0), sizeof(struct csr));
-       if(!nic->csr) {
-               DPRINTK(PROBE, ERR, "Cannot map device registers, aborting.\n");
-               err = -ENOMEM;
-               goto err_out_free_res;
-       }
-
-       e100_hw_reset(nic);
-
-       pci_set_master(pdev);
-
        if((err = pci_set_dma_mask(pdev, 0xFFFFFFFFULL))) {
                DPRINTK(PROBE, ERR, "No usable DMA configuration, aborting.\n");
-               goto err_out_iounmap;
+               goto err_out_free_res;
        }
 
        SET_MODULE_OWNER(netdev);
        SET_NETDEV_DEV(netdev, &pdev->dev);
 
+       nic->csr = ioremap(pci_resource_start(pdev, 0), sizeof(struct csr));
+       if(!nic->csr) {
+               DPRINTK(PROBE, ERR, "Cannot map device registers, aborting.\n");
+               err = -ENOMEM;
+               goto err_out_free_res;
+       }
+
        if(ent->driver_data)
                nic->flags |= ich;
        else
                nic->flags &= ~ich;
 
+       e100_get_defaults(nic);
+
        spin_lock_init(&nic->cb_lock);
        spin_lock_init(&nic->cmd_lock);
 
+       /* Reset the device before pci_set_master() in case device is in some
+        * funky state and has an interrupt pending - hint: we don't have the
+        * interrupt handler registered yet. */
+       e100_hw_reset(nic);
+
+       pci_set_master(pdev);
+
        init_timer(&nic->watchdog);
        nic->watchdog.function = e100_watchdog;
        nic->watchdog.data = (unsigned long)nic;
@@ -2243,8 +2248,6 @@ static int __devinit e100_probe(struct pci_dev *pdev,
                goto err_out_iounmap;
        }
 
-       e100_get_defaults(nic);
-       e100_hw_reset(nic);
        e100_phy_init(nic);
 
        if((err = e100_eeprom_load(nic)))