]> git.proxmox.com Git - mirror_ubuntu-eoan-kernel.git/blobdiff - drivers/net/sky2.c
[PATCH] sky2: remove cloned/pskb_expand_head check
[mirror_ubuntu-eoan-kernel.git] / drivers / net / sky2.c
index 31093760aa1e9534270e2d5a9c8746ce3ce46b14..67ebc05d9d194aa0a1e2c2d18a4edd40d0e32b85 100644 (file)
@@ -50,7 +50,7 @@
 #include "sky2.h"
 
 #define DRV_NAME               "sky2"
-#define DRV_VERSION            "1.4"
+#define DRV_VERSION            "1.6"
 #define PFX                    DRV_NAME " "
 
 /*
@@ -65,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)
@@ -120,6 +121,11 @@ static const struct pci_device_id sky2_id_table[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4361) },
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4362) },
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4363) },
+       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4364) },
+       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4365) },
+       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4366) },
+       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4367) },
+       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4368) },
        { 0 }
 };
 
@@ -232,9 +238,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;
@@ -242,8 +249,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:
@@ -255,6 +260,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);
@@ -1233,13 +1239,6 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev)
        /* Check for TCP Segmentation Offload */
        mss = skb_shinfo(skb)->gso_size;
        if (mss != 0) {
-               /* just drop the packet if non-linear expansion fails */
-               if (skb_header_cloned(skb) &&
-                   pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) {
-                       dev_kfree_skb(skb);
-                       goto out_unlock;
-               }
-
                mss += ((skb->h.th->doff - 5) * 4);     /* TCP options */
                mss += (skb->nh.iph->ihl * 4) + sizeof(struct tcphdr);
                mss += ETH_HLEN;
@@ -1335,7 +1334,6 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev)
 
        sky2_put_idx(hw, txqaddr[sky2->port], sky2->tx_prod);
 
-out_unlock:
        spin_unlock(&sky2->tx_lock);
 
        dev->trans_start = jiffies;
@@ -1389,7 +1387,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);
 }
 
@@ -1888,9 +1886,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:
@@ -1928,16 +1923,12 @@ static inline void sky2_tx_done(struct net_device *dev, u16 last)
        }
 }
 
-/* Is status ring empty or is there more to do? */
-static inline int sky2_more_work(const struct sky2_hw *hw)
-{
-       return (hw->st_idx != sky2_read16(hw, STAT_PUT_IDX));
-}
-
 /* 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();
@@ -1945,7 +1936,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;
@@ -1978,6 +1968,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;
@@ -2015,7 +2013,20 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do)
                }
        }
 
+       /* Fully processed status ring so clear irq */
+       sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ);
+
 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;
 }
 
@@ -2186,9 +2197,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);
 
@@ -2217,19 +2225,16 @@ static int sky2_poll(struct net_device *dev0, int *budget)
                sky2_descriptor_error(hw, 1, "transmit", Y2_IS_CHK_TXA2);
 
        work_done = sky2_status_intr(hw, work_limit);
-       *budget -= work_done;
-       dev0->quota -= work_done;
-
-       if (status & Y2_IS_STAT_BMU)
-               sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ);
+       if (work_done < work_limit) {
+               netif_rx_complete(dev0);
 
-       if (sky2_more_work(hw))
+               sky2_read32(hw, B0_Y2_SP_LISR);
+               return 0;
+       } else {
+               *budget -= work_done;
+               dev0->quota -= work_done;
                return 1;
-out:
-       netif_rx_complete(dev0);
-
-       sky2_read32(hw, B0_Y2_SP_LISR);
-       return 0;
+       }
 }
 
 static irqreturn_t sky2_intr(int irq, void *dev_id, struct pt_regs *regs)
@@ -2286,7 +2291,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;
@@ -3437,17 +3442,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);
                }
        }
 
@@ -3474,9 +3476,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) {
@@ -3488,6 +3489,7 @@ static int sky2_resume(struct pci_dev *pdev)
                }
        }
 
+       netif_poll_enable(hw->dev[0]);
        sky2_idle_start(hw);
 out:
        return err;