Remove obsolete #include <linux/config.h>
[cascardo/linux.git] / drivers / net / e100.c
index 24253c8..a1d676a 100644 (file)
  *     - Stratus87247: protect MDI control register manipulations
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/kernel.h>
@@ -598,8 +597,8 @@ static void e100_enable_irq(struct nic *nic)
 
        spin_lock_irqsave(&nic->cmd_lock, flags);
        writeb(irq_mask_none, &nic->csr->scb.cmd_hi);
-       spin_unlock_irqrestore(&nic->cmd_lock, flags);
        e100_write_flush(nic);
+       spin_unlock_irqrestore(&nic->cmd_lock, flags);
 }
 
 static void e100_disable_irq(struct nic *nic)
@@ -608,8 +607,8 @@ static void e100_disable_irq(struct nic *nic)
 
        spin_lock_irqsave(&nic->cmd_lock, flags);
        writeb(irq_mask_all, &nic->csr->scb.cmd_hi);
-       spin_unlock_irqrestore(&nic->cmd_lock, flags);
        e100_write_flush(nic);
+       spin_unlock_irqrestore(&nic->cmd_lock, flags);
 }
 
 static void e100_hw_reset(struct nic *nic)
@@ -1582,8 +1581,8 @@ static void e100_watchdog(unsigned long data)
         * interrupt mask bit and the SW Interrupt generation bit */
        spin_lock_irq(&nic->cmd_lock);
        writeb(readb(&nic->csr->scb.cmd_hi) | irq_sw_gen,&nic->csr->scb.cmd_hi);
-       spin_unlock_irq(&nic->cmd_lock);
        e100_write_flush(nic);
+       spin_unlock_irq(&nic->cmd_lock);
 
        e100_update_stats(nic);
        e100_adjust_adaptive_ifs(nic, cmd.speed, cmd.duplex);
@@ -2154,6 +2153,9 @@ static int e100_loopback_test(struct nic *nic, enum loopback loopback_mode)
 
        msleep(10);
 
+       pci_dma_sync_single_for_cpu(nic->pdev, nic->rx_to_clean->dma_addr,
+                       RFD_BUF_LEN, PCI_DMA_FROMDEVICE);
+
        if(memcmp(nic->rx_to_clean->skb->data + sizeof(struct rfd),
           skb->data, ETH_DATA_LEN))
                err = -EAGAIN;
@@ -2161,8 +2163,8 @@ static int e100_loopback_test(struct nic *nic, enum loopback loopback_mode)
 err_loopback_none:
        mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, 0);
        nic->loopback = lb_none;
-       e100_hw_init(nic);
        e100_clean_cbs(nic);
+       e100_hw_reset(nic);
 err_clean_rx:
        e100_rx_clean_list(nic);
        return err;
@@ -2675,9 +2677,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]);
 
@@ -2777,6 +2779,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,
@@ -2788,6 +2864,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)