[PATCH] bcm43xx: workaround init_board vs. IRQ race
[powerpc.git] / drivers / net / sky2.c
index 765c8f0..418f169 100644 (file)
@@ -23,7 +23,6 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/config.h>
 #include <linux/crc32.h>
 #include <linux/kernel.h>
 #include <linux/version.h>
@@ -1160,7 +1159,7 @@ static unsigned tx_le_req(const struct sk_buff *skb)
        count = sizeof(dma_addr_t) / sizeof(u32);
        count += skb_shinfo(skb)->nr_frags * count;
 
-       if (skb_shinfo(skb)->tso_size)
+       if (skb_shinfo(skb)->gso_size)
                ++count;
 
        if (skb->ip_summed == CHECKSUM_HW)
@@ -1232,7 +1231,7 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev)
        }
 
        /* Check for TCP Segmentation Offload */
-       mss = skb_shinfo(skb)->tso_size;
+       mss = skb_shinfo(skb)->gso_size;
        if (mss != 0) {
                /* just drop the packet if non-linear expansion fails */
                if (skb_header_cloned(skb) &&
@@ -2161,6 +2160,13 @@ static void sky2_descriptor_error(struct sky2_hw *hw, unsigned port,
 /* If idle then force a fake soft NAPI poll once a second
  * to work around cases where sharing an edge triggered interrupt.
  */
+static inline void sky2_idle_start(struct sky2_hw *hw)
+{
+       if (idle_timeout > 0)
+               mod_timer(&hw->idle_timer,
+                         jiffies + msecs_to_jiffies(idle_timeout));
+}
+
 static void sky2_idle(unsigned long arg)
 {
        struct sky2_hw *hw = (struct sky2_hw *) arg;
@@ -2181,7 +2187,7 @@ static int sky2_poll(struct net_device *dev0, int *budget)
        u32 status = sky2_read32(hw, B0_Y2_SP_EISR);
 
        if (!~status)
-               return 0;
+               goto out;
 
        if (status & Y2_IS_HW_ERR)
                sky2_hw_intr(hw);
@@ -2219,7 +2225,7 @@ static int sky2_poll(struct net_device *dev0, int *budget)
 
        if (sky2_more_work(hw))
                return 1;
-
+out:
        netif_rx_complete(dev0);
 
        sky2_read32(hw, B0_Y2_SP_LISR);
@@ -2248,8 +2254,10 @@ static irqreturn_t sky2_intr(int irq, void *dev_id, struct pt_regs *regs)
 static void sky2_netpoll(struct net_device *dev)
 {
        struct sky2_port *sky2 = netdev_priv(dev);
+       struct net_device *dev0 = sky2->hw->dev[0];
 
-       sky2_intr(sky2->hw->pdev->irq, sky2->hw, NULL);
+       if (netif_running(dev) && __netif_rx_schedule_prep(dev0))
+               __netif_rx_schedule(dev0);
 }
 #endif
 
@@ -3180,7 +3188,7 @@ static int __devinit sky2_test_msi(struct sky2_hw *hw)
 
        sky2_write32(hw, B0_IMSK, Y2_IS_IRQ_SW);
 
-       err = request_irq(pdev->irq, sky2_test_intr, SA_SHIRQ, DRV_NAME, hw);
+       err = request_irq(pdev->irq, sky2_test_intr, IRQF_SHARED, DRV_NAME, hw);
        if (err) {
                printk(KERN_ERR PFX "%s: cannot assign irq %d\n",
                       pci_name(pdev), pdev->irq);
@@ -3302,9 +3310,9 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
        if (err)
                goto err_out_iounmap;
 
-       printk(KERN_INFO PFX "v%s addr 0x%lx irq %d Yukon-%s (0x%x) rev %d\n",
-              DRV_VERSION, pci_resource_start(pdev, 0), pdev->irq,
-              yukon2_name[hw->chip_id - CHIP_ID_YUKON_XL],
+       printk(KERN_INFO PFX "v%s addr 0x%llx irq %d Yukon-%s (0x%x) rev %d\n",
+              DRV_VERSION, (unsigned long long)pci_resource_start(pdev, 0),
+              pdev->irq, yukon2_name[hw->chip_id - CHIP_ID_YUKON_XL],
               hw->chip_id, hw->chip_rev);
 
        dev = sky2_init_netdev(hw, 0, using_dac);
@@ -3340,7 +3348,7 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
                        goto err_out_unregister;
        }
 
-       err = request_irq(pdev->irq,  sky2_intr, SA_SHIRQ, DRV_NAME, hw);
+       err = request_irq(pdev->irq,  sky2_intr, IRQF_SHARED, DRV_NAME, hw);
        if (err) {
                printk(KERN_ERR PFX "%s: cannot assign irq %d\n",
                       pci_name(pdev), pdev->irq);
@@ -3350,9 +3358,7 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
        sky2_write32(hw, B0_IMSK, Y2_IS_BASE);
 
        setup_timer(&hw->idle_timer, sky2_idle, (unsigned long) hw);
-       if (idle_timeout > 0)
-               mod_timer(&hw->idle_timer,
-                         jiffies + msecs_to_jiffies(idle_timeout));
+       sky2_idle_start(hw);
 
        pci_set_drvdata(pdev, hw);
 
@@ -3430,7 +3436,9 @@ static int sky2_suspend(struct pci_dev *pdev, pm_message_t state)
        if (!(pstate == PCI_D3hot || pstate == PCI_D3cold))
                return -EINVAL;
 
-       for (i = 0; i < 2; i++) {
+       del_timer_sync(&hw->idle_timer);
+
+       for (i = 0; i < hw->ports; i++) {
                struct net_device *dev = hw->dev[i];
 
                if (dev) {
@@ -3439,9 +3447,11 @@ static int sky2_suspend(struct pci_dev *pdev, pm_message_t state)
 
                        sky2_down(dev);
                        netif_device_detach(dev);
+                       netif_poll_disable(dev);
                }
        }
 
+       sky2_write32(hw, B0_IMSK, 0);
        pci_save_state(pdev);
        sky2_set_power_state(hw, pstate);
        return 0;
@@ -3460,19 +3470,25 @@ static int sky2_resume(struct pci_dev *pdev)
        if (err)
                goto out;
 
-       for (i = 0; i < 2; i++) {
+       sky2_write32(hw, B0_IMSK, Y2_IS_BASE);
+
+       for (i = 0; i < hw->ports; i++) {
                struct net_device *dev = hw->dev[i];
                if (dev && netif_running(dev)) {
                        netif_device_attach(dev);
+                       netif_poll_enable(dev);
+
                        err = sky2_up(dev);
                        if (err) {
                                printk(KERN_ERR PFX "%s: could not up: %d\n",
                                       dev->name, err);
                                dev_close(dev);
-                               break;
+                               goto out;
                        }
                }
        }
+
+       sky2_idle_start(hw);
 out:
        return err;
 }