Merge branch 'upstream-greg' of gregkh@master.kernel.org:/pub/scm/linux/kernel/git...
[pandora-kernel.git] / drivers / net / sky2.c
index d357787..933e87f 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>
@@ -51,7 +50,7 @@
 #include "sky2.h"
 
 #define DRV_NAME               "sky2"
-#define DRV_VERSION            "1.4"
+#define DRV_VERSION            "1.5"
 #define PFX                    DRV_NAME " "
 
 /*
@@ -66,6 +65,7 @@
 #define RX_MAX_PENDING         (RX_LE_SIZE/2 - 2)
 #define RX_DEF_PENDING         RX_MAX_PENDING
 #define RX_SKB_ALIGN           8
+#define RX_BUF_WRITE           16
 
 #define TX_RING_SIZE           512
 #define TX_DEF_PENDING         (TX_RING_SIZE - 1)
@@ -233,9 +233,10 @@ static void sky2_set_power_state(struct sky2_hw *hw, pci_power_t state)
                        if (hw->ports > 1)
                                reg1 |= PCI_Y2_PHY2_COMA;
                }
+               sky2_pci_write32(hw, PCI_DEV_REG1, reg1);
+               udelay(100);
 
                if (hw->chip_id == CHIP_ID_YUKON_EC_U) {
-                       sky2_write16(hw, B0_CTST, Y2_HW_WOL_ON);
                        sky2_pci_write32(hw, PCI_DEV_REG3, 0);
                        reg1 = sky2_pci_read32(hw, PCI_DEV_REG4);
                        reg1 &= P_ASPM_CONTROL_MSK;
@@ -243,8 +244,6 @@ static void sky2_set_power_state(struct sky2_hw *hw, pci_power_t state)
                        sky2_pci_write32(hw, PCI_DEV_REG5, 0);
                }
 
-               sky2_pci_write32(hw, PCI_DEV_REG1, reg1);
-
                break;
 
        case PCI_D3hot:
@@ -256,6 +255,7 @@ static void sky2_set_power_state(struct sky2_hw *hw, pci_power_t state)
                else
                        reg1 |= (PCI_Y2_PHY1_POWD | PCI_Y2_PHY2_POWD);
                sky2_pci_write32(hw, PCI_DEV_REG1, reg1);
+               udelay(100);
 
                if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > 1)
                        sky2_write8(hw, B2_Y2_CLK_GATE, 0);
@@ -1160,7 +1160,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)->gso_size)
+       if (skb_is_gso(skb))
                ++count;
 
        if (skb->ip_summed == CHECKSUM_HW)
@@ -1390,7 +1390,7 @@ static void sky2_tx_complete(struct sky2_port *sky2, u16 done)
        }
 
        sky2->tx_cons = put;
-       if (tx_avail(sky2) > MAX_SKB_TX_LE)
+       if (tx_avail(sky2) > MAX_SKB_TX_LE + 4)
                netif_wake_queue(dev);
 }
 
@@ -1889,9 +1889,6 @@ resubmit:
        re->skb->ip_summed = CHECKSUM_NONE;
        sky2_rx_add(sky2, re->mapaddr);
 
-       /* Tell receiver about new buffers. */
-       sky2_put_idx(sky2->hw, rxqaddr[sky2->port], sky2->rx_put);
-
        return skb;
 
 oversize:
@@ -1938,7 +1935,9 @@ static inline int sky2_more_work(const struct sky2_hw *hw)
 /* Process status response ring */
 static int sky2_status_intr(struct sky2_hw *hw, int to_do)
 {
+       struct sky2_port *sky2;
        int work_done = 0;
+       unsigned buf_write[2] = { 0, 0 };
        u16 hwidx = sky2_read16(hw, STAT_PUT_IDX);
 
        rmb();
@@ -1946,7 +1945,6 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do)
        while (hw->st_idx != hwidx) {
                struct sky2_status_le *le  = hw->st_le + hw->st_idx;
                struct net_device *dev;
-               struct sky2_port *sky2;
                struct sk_buff *skb;
                u32 status;
                u16 length;
@@ -1979,6 +1977,14 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do)
 #endif
                                netif_receive_skb(skb);
 
+                       /* Update receiver after 16 frames */
+                       if (++buf_write[le->link] == RX_BUF_WRITE) {
+                               sky2_put_idx(hw, rxqaddr[le->link],
+                                            sky2->rx_put);
+                               buf_write[le->link] = 0;
+                       }
+
+                       /* Stop after net poll weight */
                        if (++work_done >= to_do)
                                goto exit_loop;
                        break;
@@ -2017,6 +2023,16 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do)
        }
 
 exit_loop:
+       if (buf_write[0]) {
+               sky2 = netdev_priv(hw->dev[0]);
+               sky2_put_idx(hw, Q_R1, sky2->rx_put);
+       }
+
+       if (buf_write[1]) {
+               sky2 = netdev_priv(hw->dev[1]);
+               sky2_put_idx(hw, Q_R2, sky2->rx_put);
+       }
+
        return work_done;
 }
 
@@ -2187,9 +2203,6 @@ static int sky2_poll(struct net_device *dev0, int *budget)
        int work_done = 0;
        u32 status = sky2_read32(hw, B0_Y2_SP_EISR);
 
-       if (!~status)
-               goto out;
-
        if (status & Y2_IS_HW_ERR)
                sky2_hw_intr(hw);
 
@@ -2226,7 +2239,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);
@@ -2287,7 +2300,7 @@ static inline u32 sky2_clk2us(const struct sky2_hw *hw, u32 clk)
 }
 
 
-static int __devinit sky2_reset(struct sky2_hw *hw)
+static int sky2_reset(struct sky2_hw *hw)
 {
        u16 status;
        u8 t8, pmd_type;
@@ -3189,7 +3202,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);
@@ -3311,9 +3324,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);
@@ -3349,7 +3362,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);
@@ -3438,17 +3451,14 @@ static int sky2_suspend(struct pci_dev *pdev, pm_message_t state)
                return -EINVAL;
 
        del_timer_sync(&hw->idle_timer);
+       netif_poll_disable(hw->dev[0]);
 
        for (i = 0; i < hw->ports; i++) {
                struct net_device *dev = hw->dev[i];
 
-               if (dev) {
-                       if (!netif_running(dev))
-                               continue;
-
+               if (netif_running(dev)) {
                        sky2_down(dev);
                        netif_device_detach(dev);
-                       netif_poll_disable(dev);
                }
        }
 
@@ -3475,9 +3485,8 @@ static int sky2_resume(struct pci_dev *pdev)
 
        for (i = 0; i < hw->ports; i++) {
                struct net_device *dev = hw->dev[i];
-               if (dev && netif_running(dev)) {
+               if (netif_running(dev)) {
                        netif_device_attach(dev);
-                       netif_poll_enable(dev);
 
                        err = sky2_up(dev);
                        if (err) {
@@ -3489,6 +3498,7 @@ static int sky2_resume(struct pci_dev *pdev)
                }
        }
 
+       netif_poll_enable(hw->dev[0]);
        sky2_idle_start(hw);
 out:
        return err;