Merge to Fedora kernel-2.6.18-1.2224_FC5 patched with stable patch-2.6.18.1-vs2.0...
[linux-2.6.git] / drivers / net / e100.c
index 31ac001..ce850f1 100644 (file)
  *     - Stratus87247: protect MDI control register manipulations
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/kernel.h>
@@ -174,8 +173,11 @@ MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_VERSION);
 
 static int debug = 3;
+static int eeprom_bad_csum_allow = 0;
 module_param(debug, int, 0);
+module_param(eeprom_bad_csum_allow, int, 0);
 MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
+MODULE_PARM_DESC(eeprom_bad_csum_allow, "Allow bad eeprom checksums");
 #define DPRINTK(nlevel, klevel, fmt, args...) \
        (void)((NETIF_MSG_##nlevel & nic->msg_enable) && \
        printk(KERN_##klevel PFX "%s: %s: " fmt, nic->netdev->name, \
@@ -757,7 +759,8 @@ static int e100_eeprom_load(struct nic *nic)
        checksum = le16_to_cpu(0xBABA - checksum);
        if(checksum != nic->eeprom[nic->eeprom_wc - 1]) {
                DPRINTK(PROBE, ERR, "EEPROM corrupted\n");
-               return -EAGAIN;
+               if (!eeprom_bad_csum_allow)
+                       return -EAGAIN;
        }
 
        return 0;
@@ -2064,7 +2067,7 @@ static int e100_up(struct nic *nic)
        e100_set_multicast_list(nic->netdev);
        e100_start_receiver(nic, NULL);
        mod_timer(&nic->watchdog, jiffies);
-       if((err = request_irq(nic->pdev->irq, e100_intr, SA_SHIRQ,
+       if((err = request_irq(nic->pdev->irq, e100_intr, IRQF_SHARED,
                nic->netdev->name, nic->netdev)))
                goto err_no_irq;
        netif_wake_queue(nic->netdev);
@@ -2678,9 +2681,9 @@ static int __devinit e100_probe(struct pci_dev *pdev,
                goto err_out_free;
        }
 
-       DPRINTK(PROBE, INFO, "addr 0x%lx, irq %d, "
+       DPRINTK(PROBE, INFO, "addr 0x%llx, irq %d, "
                "MAC addr %02X:%02X:%02X:%02X:%02X:%02X\n",
-               pci_resource_start(pdev, 0), pdev->irq,
+               (unsigned long long)pci_resource_start(pdev, 0), pdev->irq,
                netdev->dev_addr[0], netdev->dev_addr[1], netdev->dev_addr[2],
                netdev->dev_addr[3], netdev->dev_addr[4], netdev->dev_addr[5]);
 
@@ -2780,6 +2783,80 @@ static void e100_shutdown(struct pci_dev *pdev)
                DPRINTK(PROBE,ERR, "Error enabling wake\n");
 }
 
+/* ------------------ PCI Error Recovery infrastructure  -------------- */
+/**
+ * e100_io_error_detected - called when PCI error is detected.
+ * @pdev: Pointer to PCI device
+ * @state: The current pci conneection state
+ */
+static pci_ers_result_t e100_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
+{
+       struct net_device *netdev = pci_get_drvdata(pdev);
+
+       /* Similar to calling e100_down(), but avoids adpater I/O. */
+       netdev->stop(netdev);
+
+       /* Detach; put netif into state similar to hotplug unplug. */
+       netif_poll_enable(netdev);
+       netif_device_detach(netdev);
+
+       /* Request a slot reset. */
+       return PCI_ERS_RESULT_NEED_RESET;
+}
+
+/**
+ * e100_io_slot_reset - called after the pci bus has been reset.
+ * @pdev: Pointer to PCI device
+ *
+ * Restart the card from scratch.
+ */
+static pci_ers_result_t e100_io_slot_reset(struct pci_dev *pdev)
+{
+       struct net_device *netdev = pci_get_drvdata(pdev);
+       struct nic *nic = netdev_priv(netdev);
+
+       if (pci_enable_device(pdev)) {
+               printk(KERN_ERR "e100: Cannot re-enable PCI device after reset.\n");
+               return PCI_ERS_RESULT_DISCONNECT;
+       }
+       pci_set_master(pdev);
+
+       /* Only one device per card can do a reset */
+       if (0 != PCI_FUNC(pdev->devfn))
+               return PCI_ERS_RESULT_RECOVERED;
+       e100_hw_reset(nic);
+       e100_phy_init(nic);
+
+       return PCI_ERS_RESULT_RECOVERED;
+}
+
+/**
+ * e100_io_resume - resume normal operations
+ * @pdev: Pointer to PCI device
+ *
+ * Resume normal operations after an error recovery
+ * sequence has been completed.
+ */
+static void e100_io_resume(struct pci_dev *pdev)
+{
+       struct net_device *netdev = pci_get_drvdata(pdev);
+       struct nic *nic = netdev_priv(netdev);
+
+       /* ack any pending wake events, disable PME */
+       pci_enable_wake(pdev, 0, 0);
+
+       netif_device_attach(netdev);
+       if (netif_running(netdev)) {
+               e100_open(netdev);
+               mod_timer(&nic->watchdog, jiffies);
+       }
+}
+
+static struct pci_error_handlers e100_err_handler = {
+       .error_detected = e100_io_error_detected,
+       .slot_reset = e100_io_slot_reset,
+       .resume = e100_io_resume,
+};
 
 static struct pci_driver e100_driver = {
        .name =         DRV_NAME,
@@ -2791,6 +2868,7 @@ static struct pci_driver e100_driver = {
        .resume =       e100_resume,
 #endif
        .shutdown =     e100_shutdown,
+       .err_handler = &e100_err_handler,
 };
 
 static int __init e100_init_module(void)