sky2: phy workarounds for Yukon EC-U A1
[powerpc.git] / drivers / net / sky2.c
index 5383997..4a009b7 100644 (file)
@@ -510,9 +510,9 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
                ledover &= ~PHY_M_LED_MO_RX;
        }
 
-       if (hw->chip_id == CHIP_ID_YUKON_EC_U && hw->chip_rev == CHIP_REV_YU_EC_A1) {
+       if (hw->chip_id == CHIP_ID_YUKON_EC_U &&
+           hw->chip_rev == CHIP_REV_YU_EC_U_A1) {
                /* apply fixes in PHY AFE */
-               pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR);
                gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 255);
 
                /* increase differential signal amplitude in 10BASE-T */
@@ -524,7 +524,7 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
                gm_phy_write(hw, port, 0x17, 0x2002);
 
                /* set page register to 0 */
-               gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg);
+               gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 0);
        } else if (hw->chip_id != CHIP_ID_YUKON_EX) {
                gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl);
 
@@ -1561,6 +1561,7 @@ static int sky2_down(struct net_device *dev)
 
        /* Stop more packets from being queued */
        netif_stop_queue(dev);
+       netif_carrier_off(dev);
 
        /* Disable port IRQ */
        imask = sky2_read32(hw, B0_IMSK);
@@ -2165,9 +2166,27 @@ force_update:
                        /* fall through */
 #endif
                case OP_RXCHKS:
-                       skb = sky2->rx_ring[sky2->rx_next].skb;
-                       skb->ip_summed = CHECKSUM_COMPLETE;
-                       skb->csum = status & 0xffff;
+                       if (!sky2->rx_csum)
+                               break;
+
+                       /* Both checksum counters are programmed to start at
+                        * the same offset, so unless there is a problem they
+                        * should match. This failure is an early indication that
+                        * hardware receive checksumming won't work.
+                        */
+                       if (likely(status >> 16 == (status & 0xffff))) {
+                               skb = sky2->rx_ring[sky2->rx_next].skb;
+                               skb->ip_summed = CHECKSUM_COMPLETE;
+                               skb->csum = status & 0xffff;
+                       } else {
+                               printk(KERN_NOTICE PFX "%s: hardware receive "
+                                      "checksum problem (status = %#x)\n",
+                                      dev->name, status);
+                               sky2->rx_csum = 0;
+                               sky2_write32(sky2->hw,
+                                            Q_ADDR(rxqaddr[le->link], Q_CSR),
+                                            BMU_DIS_RX_CHKSUM);
+                       }
                        break;
 
                case OP_TXINDEXLE:
@@ -3751,6 +3770,11 @@ static int sky2_resume(struct pci_dev *pdev)
                goto out;
 
        pci_enable_wake(pdev, PCI_D0, 0);
+
+       /* Re-enable all clocks */
+       if (hw->chip_id == CHIP_ID_YUKON_EX || hw->chip_id == CHIP_ID_YUKON_EC_U)
+               sky2_pci_write32(hw, PCI_DEV_REG3, 0);
+
        sky2_reset(hw);
 
        sky2_write32(hw, B0_IMSK, Y2_IS_BASE);