sky2: Refactor sky2_up into two functions
[safe/jmp/linux-2.6] / drivers / net / sky2.c
index edf37aa..1f0180f 100644 (file)
@@ -733,7 +733,6 @@ static void sky2_wol_init(struct sky2_port *sky2)
        unsigned port = sky2->port;
        enum flow_control save_mode;
        u16 ctrl;
-       u32 reg1;
 
        /* Bring hardware out of reset */
        sky2_write16(hw, B0_CTST, CS_RST_CLR);
@@ -787,11 +786,6 @@ static void sky2_wol_init(struct sky2_port *sky2)
        /* Disable PiG firmware */
        sky2_write16(hw, B0_CTST, Y2_HW_WOL_OFF);
 
-       /* Turn on legacy PCI-Express PME mode */
-       reg1 = sky2_pci_read32(hw, PCI_DEV_REG1);
-       reg1 |= PCI_Y2_PME_LEGACY;
-       sky2_pci_write32(hw, PCI_DEV_REG1, reg1);
-
        /* block receiver */
        sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET);
 }
@@ -804,29 +798,15 @@ static void sky2_set_tx_stfwd(struct sky2_hw *hw, unsigned port)
              hw->chip_rev != CHIP_REV_YU_EX_A0) ||
             hw->chip_id >= CHIP_ID_YUKON_FE_P) {
                /* Yukon-Extreme B0 and further Extreme devices */
-               /* enable Store & Forward mode for TX */
-
-               if (dev->mtu <= ETH_DATA_LEN)
-                       sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
-                                    TX_JUMBO_DIS | TX_STFW_ENA);
-
-               else
-                       sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
-                                    TX_JUMBO_ENA| TX_STFW_ENA);
-       } else {
-               if (dev->mtu <= ETH_DATA_LEN)
-                       sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), TX_STFW_ENA);
-               else {
-                       /* set Tx GMAC FIFO Almost Empty Threshold */
-                       sky2_write32(hw, SK_REG(port, TX_GMF_AE_THR),
-                                    (ECU_JUMBO_WM << 16) | ECU_AE_THR);
+               sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), TX_STFW_ENA);
+       } else if (dev->mtu > ETH_DATA_LEN) {
+               /* set Tx GMAC FIFO Almost Empty Threshold */
+               sky2_write32(hw, SK_REG(port, TX_GMF_AE_THR),
+                            (ECU_JUMBO_WM << 16) | ECU_AE_THR);
 
-                       sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), TX_STFW_DIS);
-
-                       /* Can't do offload because of lack of store/forward */
-                       dev->features &= ~(NETIF_F_TSO | NETIF_F_SG | NETIF_F_ALL_CSUM);
-               }
-       }
+               sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), TX_STFW_DIS);
+       } else
+               sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), TX_STFW_ENA);
 }
 
 static void sky2_mac_init(struct sky2_hw *hw, unsigned port)
@@ -1069,6 +1049,40 @@ static inline struct sky2_rx_le *sky2_next_rx(struct sky2_port *sky2)
        return le;
 }
 
+static unsigned sky2_get_rx_threshold(struct sky2_port* sky2)
+{
+       unsigned size;
+
+       /* Space needed for frame data + headers rounded up */
+       size = roundup(sky2->netdev->mtu + ETH_HLEN + VLAN_HLEN, 8);
+
+       /* Stopping point for hardware truncation */
+       return (size - 8) / sizeof(u32);
+}
+
+static unsigned sky2_get_rx_data_size(struct sky2_port* sky2)
+{
+       struct rx_ring_info *re;
+       unsigned size;
+
+       /* Space needed for frame data + headers rounded up */
+       size = roundup(sky2->netdev->mtu + ETH_HLEN + VLAN_HLEN, 8);
+
+       sky2->rx_nfrags = size >> PAGE_SHIFT;
+       BUG_ON(sky2->rx_nfrags > ARRAY_SIZE(re->frag_addr));
+
+       /* Compute residue after pages */
+       size -= sky2->rx_nfrags << PAGE_SHIFT;
+
+       /* Optimize to handle small packets and headers */
+       if (size < copybreak)
+               size = copybreak;
+       if (size < ETH_HLEN)
+               size = ETH_HLEN;
+
+       return size;
+}
+
 /* Build description to hardware for one receive segment */
 static void sky2_rx_add(struct sky2_port *sky2,  u8 op,
                        dma_addr_t map, unsigned len)
@@ -1349,8 +1363,32 @@ static inline void sky2_rx_update(struct sky2_port *sky2, unsigned rxq)
        sky2_put_idx(sky2->hw, rxq, sky2->rx_put);
 }
 
+static int sky2_alloc_rx_skbs(struct sky2_port *sky2)
+{
+       struct sky2_hw *hw = sky2->hw;
+       unsigned i;
+
+       sky2->rx_data_size = sky2_get_rx_data_size(sky2);
+
+       /* Fill Rx ring */
+       for (i = 0; i < sky2->rx_pending; i++) {
+               struct rx_ring_info *re = sky2->rx_ring + i;
+
+               re->skb = sky2_rx_alloc(sky2);
+               if (!re->skb)
+                       return -ENOMEM;
+
+               if (sky2_rx_map_skb(hw->pdev, re, sky2->rx_data_size)) {
+                       dev_kfree_skb(re->skb);
+                       re->skb = NULL;
+                       return -ENOMEM;
+               }
+       }
+       return 0;
+}
+
 /*
- * Allocate and setup receiver buffer pool.
+ * Setup receiver buffer pool.
  * Normal case this ends up creating one list element for skb
  * in the receive ring. Worst case if using large MTU and each
  * allocation falls on a different 64 bit region, that results
@@ -1358,12 +1396,12 @@ static inline void sky2_rx_update(struct sky2_port *sky2, unsigned rxq)
  * One element is used for checksum enable/disable, and one
  * extra to avoid wrap.
  */
-static int sky2_rx_start(struct sky2_port *sky2)
+static void sky2_rx_start(struct sky2_port *sky2)
 {
        struct sky2_hw *hw = sky2->hw;
        struct rx_ring_info *re;
        unsigned rxq = rxqaddr[sky2->port];
-       unsigned i, size, thresh;
+       unsigned i, thresh;
 
        sky2->rx_put = sky2->rx_next = 0;
        sky2_qset(hw, rxq);
@@ -1384,40 +1422,9 @@ static int sky2_rx_start(struct sky2_port *sky2)
        if (!(hw->flags & SKY2_HW_NEW_LE))
                rx_set_checksum(sky2);
 
-       /* Space needed for frame data + headers rounded up */
-       size = roundup(sky2->netdev->mtu + ETH_HLEN + VLAN_HLEN, 8);
-
-       /* Stopping point for hardware truncation */
-       thresh = (size - 8) / sizeof(u32);
-
-       sky2->rx_nfrags = size >> PAGE_SHIFT;
-       BUG_ON(sky2->rx_nfrags > ARRAY_SIZE(re->frag_addr));
-
-       /* Compute residue after pages */
-       size -= sky2->rx_nfrags << PAGE_SHIFT;
-
-       /* Optimize to handle small packets and headers */
-       if (size < copybreak)
-               size = copybreak;
-       if (size < ETH_HLEN)
-               size = ETH_HLEN;
-
-       sky2->rx_data_size = size;
-
-       /* Fill Rx ring */
+       /* submit Rx ring */
        for (i = 0; i < sky2->rx_pending; i++) {
                re = sky2->rx_ring + i;
-
-               re->skb = sky2_rx_alloc(sky2);
-               if (!re->skb)
-                       goto nomem;
-
-               if (sky2_rx_map_skb(hw->pdev, re, sky2->rx_data_size)) {
-                       dev_kfree_skb(re->skb);
-                       re->skb = NULL;
-                       goto nomem;
-               }
-
                sky2_rx_submit(sky2, re);
        }
 
@@ -1427,6 +1434,7 @@ static int sky2_rx_start(struct sky2_port *sky2)
         * the register is limited to 9 bits, so if you do frames > 2052
         * you better get the MTU right!
         */
+       thresh = sky2_get_rx_threshold(sky2);
        if (thresh > 0x1ff)
                sky2_write32(hw, SK_REG(sky2->port, RX_GMF_CTRL_T), RX_TRUNC_OFF);
        else {
@@ -1458,13 +1466,6 @@ static int sky2_rx_start(struct sky2_port *sky2)
                sky2_write32(hw, Q_ADDR(txqaddr[sky2->port], Q_TEST),
                             TBMU_TEST_HOME_ADD_FIX_EN | TBMU_TEST_ROUTING_ADD_FIX_EN);
        }
-
-
-
-       return 0;
-nomem:
-       sky2_rx_clean(sky2);
-       return -ENOMEM;
 }
 
 static int sky2_alloc_buffers(struct sky2_port *sky2)
@@ -1495,7 +1496,7 @@ static int sky2_alloc_buffers(struct sky2_port *sky2)
        if (!sky2->rx_ring)
                goto nomem;
 
-       return 0;
+       return sky2_alloc_rx_skbs(sky2);
 nomem:
        return -ENOMEM;
 }
@@ -1504,6 +1505,8 @@ static void sky2_free_buffers(struct sky2_port *sky2)
 {
        struct sky2_hw *hw = sky2->hw;
 
+       sky2_rx_clean(sky2);
+
        if (sky2->rx_le) {
                pci_free_consistent(hw->pdev, RX_LE_BYTES,
                                    sky2->rx_le, sky2->rx_le_map);
@@ -1522,16 +1525,16 @@ static void sky2_free_buffers(struct sky2_port *sky2)
        sky2->rx_ring = NULL;
 }
 
-/* Bring up network interface. */
-static int sky2_up(struct net_device *dev)
+static void sky2_hw_up(struct sky2_port *sky2)
 {
-       struct sky2_port *sky2 = netdev_priv(dev);
        struct sky2_hw *hw = sky2->hw;
        unsigned port = sky2->port;
-       u32 imask, ramsize;
-       int cap, err;
+       u32 ramsize;
+       int cap;
        struct net_device *otherdev = hw->dev[sky2->port^1];
 
+       tx_init(sky2);
+
        /*
         * On dual port PCI-X card, there is an problem where status
         * can be received out of order due to split transactions
@@ -1543,16 +1546,7 @@ static int sky2_up(struct net_device *dev)
                cmd = sky2_pci_read16(hw, cap + PCI_X_CMD);
                cmd &= ~PCI_X_CMD_MAX_SPLIT;
                sky2_pci_write16(hw, cap + PCI_X_CMD, cmd);
-
-       }
-
-       netif_carrier_off(dev);
-
-       err = sky2_alloc_buffers(sky2);
-       if (err)
-               goto err_out;
-
-       tx_init(sky2);
+       }
 
        sky2_mac_init(hw, port);
 
@@ -1561,7 +1555,7 @@ static int sky2_up(struct net_device *dev)
        if (ramsize > 0) {
                u32 rxspace;
 
-               pr_debug(PFX "%s: ram buffer %dK\n", dev->name, ramsize);
+               pr_debug(PFX "%s: ram buffer %dK\n", sky2->netdev->name, ramsize);
                if (ramsize < 16)
                        rxspace = ramsize / 2;
                else
@@ -1593,10 +1587,26 @@ static int sky2_up(struct net_device *dev)
        sky2_set_vlan_mode(hw, port, sky2->vlgrp != NULL);
 #endif
 
-       err = sky2_rx_start(sky2);
+       sky2_rx_start(sky2);
+}
+
+/* Bring up network interface. */
+static int sky2_up(struct net_device *dev)
+{
+       struct sky2_port *sky2 = netdev_priv(dev);
+       struct sky2_hw *hw = sky2->hw;
+       unsigned port = sky2->port;
+       u32 imask;
+       int err;
+
+       netif_carrier_off(dev);
+
+       err = sky2_alloc_buffers(sky2);
        if (err)
                goto err_out;
 
+       sky2_hw_up(sky2);
+
        /* Enable interrupts from phy/mac for port */
        imask = sky2_read32(hw, B0_IMSK);
        imask |= portirq_msk[port];
@@ -1963,8 +1973,6 @@ static int sky2_down(struct net_device *dev)
        /* Free any pending frames stuck in HW queue */
        sky2_tx_complete(sky2, sky2->tx_prod);
 
-       sky2_rx_clean(sky2);
-
        sky2_free_buffers(sky2);
 
        return 0;
@@ -2212,14 +2220,20 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu)
        u16 ctl, mode;
        u32 imask;
 
+       /* MTU size outside the spec */
        if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU)
                return -EINVAL;
 
+       /* MTU > 1500 on yukon FE and FE+ not allowed */
        if (new_mtu > ETH_DATA_LEN &&
            (hw->chip_id == CHIP_ID_YUKON_FE ||
             hw->chip_id == CHIP_ID_YUKON_FE_P))
                return -EINVAL;
 
+       /* TSO, etc on Yukon Ultra and MTU > 1500 not supported */
+       if (new_mtu > ETH_DATA_LEN && hw->chip_id == CHIP_ID_YUKON_EC_U)
+               dev->features &= ~(NETIF_F_TSO|NETIF_F_SG|NETIF_F_ALL_CSUM);
+
        if (!netif_running(dev)) {
                dev->mtu = new_mtu;
                return 0;
@@ -2254,7 +2268,11 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu)
 
        sky2_write8(hw, RB_ADDR(rxqaddr[port], RB_CTRL), RB_ENA_OP_MD);
 
-       err = sky2_rx_start(sky2);
+       err = sky2_alloc_rx_skbs(sky2);
+       if (!err)
+               sky2_rx_start(sky2);
+       else
+               sky2_rx_clean(sky2);
        sky2_write32(hw, B0_IMSK, imask);
 
        sky2_read32(hw, B0_Y2_SP_LISR);