EMAC driver: add power down mode
[safe/jmp/linux-2.6] / drivers / net / natsemi.c
index ea38da6..0a3e604 100644 (file)
@@ -108,7 +108,7 @@ static int full_duplex[MAX_UNITS];
 #define TX_TIMEOUT  (2*HZ)
 
 #define NATSEMI_HW_TIMEOUT     400
-#define NATSEMI_TIMER_FREQ     3*HZ
+#define NATSEMI_TIMER_FREQ     5*HZ
 #define NATSEMI_PG0_NREGS      64
 #define NATSEMI_RFDR_NREGS     8
 #define NATSEMI_PG1_NREGS      4
@@ -203,22 +203,8 @@ skbuff at an offset of "+2", 16-byte aligning the IP header.
 IIId. Synchronization
 
 Most operations are synchronized on the np->lock irq spinlock, except the
-performance critical codepaths:
-
-The rx process only runs in the interrupt handler. Access from outside
-the interrupt handler is only permitted after disable_irq().
-
-The rx process usually runs under the netif_tx_lock. If np->intr_tx_reap
-is set, then access is permitted under spin_lock_irq(&np->lock).
-
-Thus configuration functions that want to access everything must call
-       disable_irq(dev->irq);
-       netif_tx_lock_bh(dev);
-       spin_lock_irq(&np->lock);
-
-IV. Notes
-
-NatSemi PCI network controllers are very uncommon.
+recieve and transmit paths which are synchronised using a combination of
+hardware descriptor ownership, disabling interrupts and NAPI poll scheduling.
 
 IVb. References
 
@@ -864,6 +850,7 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev,
 
        np = netdev_priv(dev);
        netif_napi_add(dev, &np->napi, natsemi_poll, 64);
+       np->dev = dev;
 
        np->pci_dev = pdev;
        pci_set_drvdata(pdev, dev);
@@ -996,7 +983,7 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev,
    a delay.  Note that pre-2.0.34 kernels had a cache-alignment bug that
    made udelay() unreliable.
    The old method of using an ISA access as a delay, __SLOW_DOWN_IO__, is
-   depricated.
+   deprecated.
 */
 #define eeprom_delay(ee_addr)  readl(ee_addr)
 
@@ -1576,7 +1563,7 @@ static int netdev_open(struct net_device *dev)
 
        /* Set the timer to check for link beat. */
        init_timer(&np->timer);
-       np->timer.expires = jiffies + NATSEMI_TIMER_FREQ;
+       np->timer.expires = round_jiffies(jiffies + NATSEMI_TIMER_FREQ);
        np->timer.data = (unsigned long)dev;
        np->timer.function = &netdev_timer; /* timer handler */
        add_timer(&np->timer);
@@ -1615,7 +1602,7 @@ static void do_cable_magic(struct net_device *dev)
                 * (these values all come from National)
                 */
                if (!(data & 0x80) || ((data >= 0xd8) && (data <= 0xff))) {
-                       struct netdev_private *np = netdev_priv(dev);
+                       np = netdev_priv(dev);
 
                        /* the bug has been triggered - fix the coefficient */
                        writew(TSTDAT_FIXED, ioaddr + TSTDAT);
@@ -1798,7 +1785,7 @@ static void netdev_timer(unsigned long data)
        struct net_device *dev = (struct net_device *)data;
        struct netdev_private *np = netdev_priv(dev);
        void __iomem * ioaddr = ns_ioaddr(dev);
-       int next_tick = 5*HZ;
+       int next_tick = NATSEMI_TIMER_FREQ;
 
        if (netif_msg_timer(np)) {
                /* DO NOT read the IntrStatus register,
@@ -1856,7 +1843,11 @@ static void netdev_timer(unsigned long data)
                        next_tick = 1;
                }
        }
-       mod_timer(&np->timer, jiffies + next_tick);
+
+       if (next_tick > 1)
+               mod_timer(&np->timer, round_jiffies(jiffies + next_tick));
+       else
+               mod_timer(&np->timer, jiffies + next_tick);
 }
 
 static void dump_ring(struct net_device *dev)
@@ -2261,7 +2252,7 @@ static int natsemi_poll(struct napi_struct *napi, int budget)
        /* Reenable interrupts providing nothing is trying to shut
         * the chip down. */
        spin_lock(&np->lock);
-       if (!np->hands_off && netif_running(dev))
+       if (!np->hands_off)
                natsemi_irq_enable(dev);
        spin_unlock(&np->lock);
 
@@ -2502,8 +2493,8 @@ static void __set_rx_mode(struct net_device *dev)
                memset(mc_filter, 0, sizeof(mc_filter));
                for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
                         i++, mclist = mclist->next) {
-                       int i = (ether_crc(ETH_ALEN, mclist->dmi_addr) >> 23) & 0x1ff;
-                       mc_filter[i/8] |= (1 << (i & 0x07));
+                       int b = (ether_crc(ETH_ALEN, mclist->dmi_addr) >> 23) & 0x1ff;
+                       mc_filter[b/8] |= (1 << (b & 0x07));
                }
                rx_mode = RxFilterEnable | AcceptBroadcast
                        | AcceptMulticast | AcceptMyPhys;
@@ -3310,13 +3301,19 @@ static int natsemi_resume (struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata (pdev);
        struct netdev_private *np = netdev_priv(dev);
+       int ret = 0;
 
        rtnl_lock();
        if (netif_device_present(dev))
                goto out;
        if (netif_running(dev)) {
                BUG_ON(!np->hands_off);
-               pci_enable_device(pdev);
+               ret = pci_enable_device(pdev);
+               if (ret < 0) {
+                       dev_err(&pdev->dev,
+                               "pci_enable_device() failed: %d\n", ret);
+                       goto out;
+               }
        /*      pci_power_on(pdev); */
 
                napi_enable(&np->napi);
@@ -3331,12 +3328,12 @@ static int natsemi_resume (struct pci_dev *pdev)
                spin_unlock_irq(&np->lock);
                enable_irq(dev->irq);
 
-               mod_timer(&np->timer, jiffies + 1*HZ);
+               mod_timer(&np->timer, round_jiffies(jiffies + 1*HZ));
        }
        netif_device_attach(dev);
 out:
        rtnl_unlock();
-       return 0;
+       return ret;
 }
 
 #endif /* CONFIG_PM */