tg3: Fix NETIF_F_LOOPBACK error
[pandora-kernel.git] / drivers / net / tg3.c
index 004f266..284e998 100644 (file)
@@ -88,10 +88,10 @@ static inline void _tg3_flag_clear(enum TG3_FLAGS flag, unsigned long *bits)
 
 #define DRV_MODULE_NAME                "tg3"
 #define TG3_MAJ_NUM                    3
-#define TG3_MIN_NUM                    118
+#define TG3_MIN_NUM                    119
 #define DRV_MODULE_VERSION     \
        __stringify(TG3_MAJ_NUM) "." __stringify(TG3_MIN_NUM)
-#define DRV_MODULE_RELDATE     "April 22, 2011"
+#define DRV_MODULE_RELDATE     "May 18, 2011"
 
 #define TG3_DEF_MAC_MODE       0
 #define TG3_DEF_RX_MODE                0
@@ -364,7 +364,6 @@ static const struct {
        { "dma_write_prioq_full" },
        { "rxbds_empty" },
        { "rx_discards" },
-       { "mbuf_lwm_thresh_hit" },
        { "rx_errors" },
        { "rx_threshold_hit" },
 
@@ -376,7 +375,9 @@ static const struct {
        { "ring_status_update" },
        { "nic_irqs" },
        { "nic_avoided_irqs" },
-       { "nic_tx_threshold_hit" }
+       { "nic_tx_threshold_hit" },
+
+       { "mbuf_lwm_thresh_hit" },
 };
 
 #define TG3_NUM_STATS  ARRAY_SIZE(ethtool_stats_keys)
@@ -552,7 +553,7 @@ static void tg3_write_mem(struct tg3 *tp, u32 off, u32 val)
 {
        unsigned long flags;
 
-       if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) &&
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906 &&
            (off >= NIC_SRAM_STATS_BLK) && (off < NIC_SRAM_TX_BUFFER_DESC))
                return;
 
@@ -577,7 +578,7 @@ static void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val)
 {
        unsigned long flags;
 
-       if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) &&
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906 &&
            (off >= NIC_SRAM_STATS_BLK) && (off < NIC_SRAM_TX_BUFFER_DESC)) {
                *val = 0;
                return;
@@ -1822,22 +1823,9 @@ static void tg3_phy_eee_adjust(struct tg3 *tp, u32 current_link_up)
                tg3_phy_cl45_read(tp, MDIO_MMD_AN,
                                  TG3_CL45_D7_EEERES_STAT, &val);
 
-               switch (val) {
-               case TG3_CL45_D7_EEERES_STAT_LP_1000T:
-                       switch (GET_ASIC_REV(tp->pci_chip_rev_id)) {
-                       case ASIC_REV_5717:
-                       case ASIC_REV_5719:
-                       case ASIC_REV_57765:
-                               if (!TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) {
-                                       tg3_phydsp_write(tp, MII_TG3_DSP_TAP26,
-                                                        0x0000);
-                                       TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);
-                               }
-                       }
-                       /* Fallthrough */
-               case TG3_CL45_D7_EEERES_STAT_LP_100TX:
+               if (val == TG3_CL45_D7_EEERES_STAT_LP_1000T ||
+                   val == TG3_CL45_D7_EEERES_STAT_LP_100TX)
                        tp->setlpicnt = 2;
-               }
        }
 
        if (!tp->setlpicnt) {
@@ -1846,6 +1834,23 @@ static void tg3_phy_eee_adjust(struct tg3 *tp, u32 current_link_up)
        }
 }
 
+static void tg3_phy_eee_enable(struct tg3 *tp)
+{
+       u32 val;
+
+       if (tp->link_config.active_speed == SPEED_1000 &&
+           (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
+            GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 ||
+            GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) &&
+           !TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) {
+               tg3_phydsp_write(tp, MII_TG3_DSP_TAP26, 0x0003);
+               TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);
+       }
+
+       val = tr32(TG3_CPMU_EEE_MODE);
+       tw32(TG3_CPMU_EEE_MODE, val | TG3_CPMU_EEEMD_LPI_ENABLE);
+}
+
 static int tg3_wait_macro_done(struct tg3 *tp)
 {
        int limit = 100;
@@ -2801,7 +2806,7 @@ static int tg3_power_down_prepare(struct tg3 *tp)
                            CLOCK_CTRL_PWRDOWN_PLL133, 40);
        } else if (tg3_flag(tp, 5780_CLASS) ||
                   tg3_flag(tp, CPMU_PRESENT) ||
-                  (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)) {
+                  GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
                /* do nothing */
        } else if (!(tg3_flag(tp, 5750_PLUS) && tg3_flag(tp, ENABLE_ASF))) {
                u32 newbits1, newbits2;
@@ -2925,102 +2930,54 @@ static void tg3_aux_stat_to_speed_duplex(struct tg3 *tp, u32 val, u16 *speed, u8
        }
 }
 
-static void tg3_phy_copper_begin(struct tg3 *tp)
+static int tg3_phy_autoneg_cfg(struct tg3 *tp, u32 advertise, u32 flowctrl)
 {
-       u32 new_adv;
-       int i;
-
-       if (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) {
-               /* Entering low power mode.  Disable gigabit and
-                * 100baseT advertisements.
-                */
-               tg3_writephy(tp, MII_TG3_CTRL, 0);
+       int err = 0;
+       u32 val, new_adv;
 
-               new_adv = (ADVERTISE_10HALF | ADVERTISE_10FULL |
-                          ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP);
-               if (tg3_flag(tp, WOL_SPEED_100MB))
-                       new_adv |= (ADVERTISE_100HALF | ADVERTISE_100FULL);
+       new_adv = ADVERTISE_CSMA;
+       if (advertise & ADVERTISED_10baseT_Half)
+               new_adv |= ADVERTISE_10HALF;
+       if (advertise & ADVERTISED_10baseT_Full)
+               new_adv |= ADVERTISE_10FULL;
+       if (advertise & ADVERTISED_100baseT_Half)
+               new_adv |= ADVERTISE_100HALF;
+       if (advertise & ADVERTISED_100baseT_Full)
+               new_adv |= ADVERTISE_100FULL;
 
-               tg3_writephy(tp, MII_ADVERTISE, new_adv);
-       } else if (tp->link_config.speed == SPEED_INVALID) {
-               if (tp->phy_flags & TG3_PHYFLG_10_100_ONLY)
-                       tp->link_config.advertising &=
-                               ~(ADVERTISED_1000baseT_Half |
-                                 ADVERTISED_1000baseT_Full);
+       new_adv |= tg3_advert_flowctrl_1000T(flowctrl);
 
-               new_adv = ADVERTISE_CSMA;
-               if (tp->link_config.advertising & ADVERTISED_10baseT_Half)
-                       new_adv |= ADVERTISE_10HALF;
-               if (tp->link_config.advertising & ADVERTISED_10baseT_Full)
-                       new_adv |= ADVERTISE_10FULL;
-               if (tp->link_config.advertising & ADVERTISED_100baseT_Half)
-                       new_adv |= ADVERTISE_100HALF;
-               if (tp->link_config.advertising & ADVERTISED_100baseT_Full)
-                       new_adv |= ADVERTISE_100FULL;
-
-               new_adv |= tg3_advert_flowctrl_1000T(tp->link_config.flowctrl);
-
-               tg3_writephy(tp, MII_ADVERTISE, new_adv);
-
-               if (tp->link_config.advertising &
-                   (ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full)) {
-                       new_adv = 0;
-                       if (tp->link_config.advertising & ADVERTISED_1000baseT_Half)
-                               new_adv |= MII_TG3_CTRL_ADV_1000_HALF;
-                       if (tp->link_config.advertising & ADVERTISED_1000baseT_Full)
-                               new_adv |= MII_TG3_CTRL_ADV_1000_FULL;
-                       if (!(tp->phy_flags & TG3_PHYFLG_10_100_ONLY) &&
-                           (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 ||
-                            tp->pci_chip_rev_id == CHIPREV_ID_5701_B0))
-                               new_adv |= (MII_TG3_CTRL_AS_MASTER |
-                                           MII_TG3_CTRL_ENABLE_AS_MASTER);
-                       tg3_writephy(tp, MII_TG3_CTRL, new_adv);
-               } else {
-                       tg3_writephy(tp, MII_TG3_CTRL, 0);
-               }
-       } else {
-               new_adv = tg3_advert_flowctrl_1000T(tp->link_config.flowctrl);
-               new_adv |= ADVERTISE_CSMA;
+       err = tg3_writephy(tp, MII_ADVERTISE, new_adv);
+       if (err)
+               goto done;
 
-               /* Asking for a specific link mode. */
-               if (tp->link_config.speed == SPEED_1000) {
-                       tg3_writephy(tp, MII_ADVERTISE, new_adv);
+       if (tp->phy_flags & TG3_PHYFLG_10_100_ONLY)
+               goto done;
 
-                       if (tp->link_config.duplex == DUPLEX_FULL)
-                               new_adv = MII_TG3_CTRL_ADV_1000_FULL;
-                       else
-                               new_adv = MII_TG3_CTRL_ADV_1000_HALF;
-                       if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 ||
-                           tp->pci_chip_rev_id == CHIPREV_ID_5701_B0)
-                               new_adv |= (MII_TG3_CTRL_AS_MASTER |
-                                           MII_TG3_CTRL_ENABLE_AS_MASTER);
-               } else {
-                       if (tp->link_config.speed == SPEED_100) {
-                               if (tp->link_config.duplex == DUPLEX_FULL)
-                                       new_adv |= ADVERTISE_100FULL;
-                               else
-                                       new_adv |= ADVERTISE_100HALF;
-                       } else {
-                               if (tp->link_config.duplex == DUPLEX_FULL)
-                                       new_adv |= ADVERTISE_10FULL;
-                               else
-                                       new_adv |= ADVERTISE_10HALF;
-                       }
-                       tg3_writephy(tp, MII_ADVERTISE, new_adv);
+       new_adv = 0;
+       if (advertise & ADVERTISED_1000baseT_Half)
+               new_adv |= MII_TG3_CTRL_ADV_1000_HALF;
+       if (advertise & ADVERTISED_1000baseT_Full)
+               new_adv |= MII_TG3_CTRL_ADV_1000_FULL;
 
-                       new_adv = 0;
-               }
+       if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 ||
+           tp->pci_chip_rev_id == CHIPREV_ID_5701_B0)
+               new_adv |= (MII_TG3_CTRL_AS_MASTER |
+                           MII_TG3_CTRL_ENABLE_AS_MASTER);
 
-               tg3_writephy(tp, MII_TG3_CTRL, new_adv);
-       }
+       err = tg3_writephy(tp, MII_TG3_CTRL, new_adv);
+       if (err)
+               goto done;
 
-       if (tp->phy_flags & TG3_PHYFLG_EEE_CAP) {
-               u32 val;
+       if (!(tp->phy_flags & TG3_PHYFLG_EEE_CAP))
+               goto done;
 
-               tw32(TG3_CPMU_EEE_MODE,
-                    tr32(TG3_CPMU_EEE_MODE) & ~TG3_CPMU_EEEMD_LPI_ENABLE);
+       tw32(TG3_CPMU_EEE_MODE,
+            tr32(TG3_CPMU_EEE_MODE) & ~TG3_CPMU_EEEMD_LPI_ENABLE);
 
-               TG3_PHY_AUXCTL_SMDSP_ENABLE(tp);
+       err = TG3_PHY_AUXCTL_SMDSP_ENABLE(tp);
+       if (!err) {
+               u32 err2;
 
                switch (GET_ASIC_REV(tp->pci_chip_rev_id)) {
                case ASIC_REV_5717:
@@ -3037,19 +2994,66 @@ static void tg3_phy_copper_begin(struct tg3 *tp)
                }
 
                val = 0;
-               if (tp->link_config.autoneg == AUTONEG_ENABLE) {
-                       /* Advertise 100-BaseTX EEE ability */
-                       if (tp->link_config.advertising &
-                           ADVERTISED_100baseT_Full)
-                               val |= MDIO_AN_EEE_ADV_100TX;
-                       /* Advertise 1000-BaseT EEE ability */
-                       if (tp->link_config.advertising &
-                           ADVERTISED_1000baseT_Full)
-                               val |= MDIO_AN_EEE_ADV_1000T;
+               /* Advertise 100-BaseTX EEE ability */
+               if (advertise & ADVERTISED_100baseT_Full)
+                       val |= MDIO_AN_EEE_ADV_100TX;
+               /* Advertise 1000-BaseT EEE ability */
+               if (advertise & ADVERTISED_1000baseT_Full)
+                       val |= MDIO_AN_EEE_ADV_1000T;
+               err = tg3_phy_cl45_write(tp, MDIO_MMD_AN, MDIO_AN_EEE_ADV, val);
+
+               err2 = TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);
+               if (!err)
+                       err = err2;
+       }
+
+done:
+       return err;
+}
+
+static void tg3_phy_copper_begin(struct tg3 *tp)
+{
+       u32 new_adv;
+       int i;
+
+       if (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) {
+               new_adv = ADVERTISED_10baseT_Half |
+                         ADVERTISED_10baseT_Full;
+               if (tg3_flag(tp, WOL_SPEED_100MB))
+                       new_adv |= ADVERTISED_100baseT_Half |
+                                  ADVERTISED_100baseT_Full;
+
+               tg3_phy_autoneg_cfg(tp, new_adv,
+                                   FLOW_CTRL_TX | FLOW_CTRL_RX);
+       } else if (tp->link_config.speed == SPEED_INVALID) {
+               if (tp->phy_flags & TG3_PHYFLG_10_100_ONLY)
+                       tp->link_config.advertising &=
+                               ~(ADVERTISED_1000baseT_Half |
+                                 ADVERTISED_1000baseT_Full);
+
+               tg3_phy_autoneg_cfg(tp, tp->link_config.advertising,
+                                   tp->link_config.flowctrl);
+       } else {
+               /* Asking for a specific link mode. */
+               if (tp->link_config.speed == SPEED_1000) {
+                       if (tp->link_config.duplex == DUPLEX_FULL)
+                               new_adv = ADVERTISED_1000baseT_Full;
+                       else
+                               new_adv = ADVERTISED_1000baseT_Half;
+               } else if (tp->link_config.speed == SPEED_100) {
+                       if (tp->link_config.duplex == DUPLEX_FULL)
+                               new_adv = ADVERTISED_100baseT_Full;
+                       else
+                               new_adv = ADVERTISED_100baseT_Half;
+               } else {
+                       if (tp->link_config.duplex == DUPLEX_FULL)
+                               new_adv = ADVERTISED_10baseT_Full;
+                       else
+                               new_adv = ADVERTISED_10baseT_Half;
                }
-               tg3_phy_cl45_write(tp, MDIO_MMD_AN, MDIO_AN_EEE_ADV, val);
 
-               TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);
+               tg3_phy_autoneg_cfg(tp, new_adv,
+                                   tp->link_config.flowctrl);
        }
 
        if (tp->link_config.autoneg == AUTONEG_DISABLE &&
@@ -3373,8 +3377,8 @@ relink:
                tg3_phy_copper_begin(tp);
 
                tg3_readphy(tp, MII_BMSR, &bmsr);
-               if (!tg3_readphy(tp, MII_BMSR, &bmsr) &&
-                   (bmsr & BMSR_LSTATUS))
+               if ((!tg3_readphy(tp, MII_BMSR, &bmsr) && (bmsr & BMSR_LSTATUS)) ||
+                   (tp->mac_mode & MAC_MODE_PORT_INT_LPBACK))
                        current_link_up = 1;
        }
 
@@ -5735,18 +5739,62 @@ static inline int tg3_40bit_overflow_test(struct tg3 *tp, dma_addr_t mapping,
 #endif
 }
 
-static void tg3_set_txd(struct tg3_napi *, int, dma_addr_t, int, u32, u32);
+static void tg3_set_txd(struct tg3_napi *tnapi, int entry,
+                       dma_addr_t mapping, int len, u32 flags,
+                       u32 mss_and_is_end)
+{
+       struct tg3_tx_buffer_desc *txd = &tnapi->tx_ring[entry];
+       int is_end = (mss_and_is_end & 0x1);
+       u32 mss = (mss_and_is_end >> 1);
+       u32 vlan_tag = 0;
+
+       if (is_end)
+               flags |= TXD_FLAG_END;
+       if (flags & TXD_FLAG_VLAN) {
+               vlan_tag = flags >> 16;
+               flags &= 0xffff;
+       }
+       vlan_tag |= (mss << TXD_MSS_SHIFT);
+
+       txd->addr_hi = ((u64) mapping >> 32);
+       txd->addr_lo = ((u64) mapping & 0xffffffff);
+       txd->len_flags = (len << TXD_LEN_SHIFT) | flags;
+       txd->vlan_tag = vlan_tag << TXD_VLAN_TAG_SHIFT;
+}
+
+static void tg3_skb_error_unmap(struct tg3_napi *tnapi,
+                               struct sk_buff *skb, int last)
+{
+       int i;
+       u32 entry = tnapi->tx_prod;
+       struct ring_info *txb = &tnapi->tx_buffers[entry];
+
+       pci_unmap_single(tnapi->tp->pdev,
+                        dma_unmap_addr(txb, mapping),
+                        skb_headlen(skb),
+                        PCI_DMA_TODEVICE);
+       for (i = 0; i <= last; i++) {
+               skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+
+               entry = NEXT_TX(entry);
+               txb = &tnapi->tx_buffers[entry];
+
+               pci_unmap_page(tnapi->tp->pdev,
+                              dma_unmap_addr(txb, mapping),
+                              frag->size, PCI_DMA_TODEVICE);
+       }
+}
 
 /* Workaround 4GB and 40-bit hardware DMA bugs. */
 static int tigon3_dma_hwbug_workaround(struct tg3_napi *tnapi,
-                                      struct sk_buff *skb, u32 last_plus_one,
-                                      u32 *start, u32 base_flags, u32 mss)
+                                      struct sk_buff *skb,
+                                      u32 base_flags, u32 mss)
 {
        struct tg3 *tp = tnapi->tp;
        struct sk_buff *new_skb;
        dma_addr_t new_addr = 0;
-       u32 entry = *start;
-       int i, ret = 0;
+       u32 entry = tnapi->tx_prod;
+       int ret = 0;
 
        if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701)
                new_skb = skb_copy(skb, GFP_ATOMIC);
@@ -5762,14 +5810,12 @@ static int tigon3_dma_hwbug_workaround(struct tg3_napi *tnapi,
                ret = -1;
        } else {
                /* New SKB is guaranteed to be linear. */
-               entry = *start;
                new_addr = pci_map_single(tp->pdev, new_skb->data, new_skb->len,
                                          PCI_DMA_TODEVICE);
                /* Make sure the mapping succeeded */
                if (pci_dma_mapping_error(tp->pdev, new_addr)) {
                        ret = -1;
                        dev_kfree_skb(new_skb);
-                       new_skb = NULL;
 
                /* Make sure new skb does not cross any 4G boundaries.
                 * Drop the packet if it does.
@@ -5780,37 +5826,14 @@ static int tigon3_dma_hwbug_workaround(struct tg3_napi *tnapi,
                                         PCI_DMA_TODEVICE);
                        ret = -1;
                        dev_kfree_skb(new_skb);
-                       new_skb = NULL;
                } else {
+                       tnapi->tx_buffers[entry].skb = new_skb;
+                       dma_unmap_addr_set(&tnapi->tx_buffers[entry],
+                                          mapping, new_addr);
+
                        tg3_set_txd(tnapi, entry, new_addr, new_skb->len,
                                    base_flags, 1 | (mss << 1));
-                       *start = NEXT_TX(entry);
-               }
-       }
-
-       /* Now clean up the sw ring entries. */
-       i = 0;
-       while (entry != last_plus_one) {
-               int len;
-
-               if (i == 0)
-                       len = skb_headlen(skb);
-               else
-                       len = skb_shinfo(skb)->frags[i-1].size;
-
-               pci_unmap_single(tp->pdev,
-                                dma_unmap_addr(&tnapi->tx_buffers[entry],
-                                               mapping),
-                                len, PCI_DMA_TODEVICE);
-               if (i == 0) {
-                       tnapi->tx_buffers[entry].skb = new_skb;
-                       dma_unmap_addr_set(&tnapi->tx_buffers[entry], mapping,
-                                          new_addr);
-               } else {
-                       tnapi->tx_buffers[entry].skb = NULL;
                }
-               entry = NEXT_TX(entry);
-               i++;
        }
 
        dev_kfree_skb(skb);
@@ -5818,202 +5841,7 @@ static int tigon3_dma_hwbug_workaround(struct tg3_napi *tnapi,
        return ret;
 }
 
-static void tg3_set_txd(struct tg3_napi *tnapi, int entry,
-                       dma_addr_t mapping, int len, u32 flags,
-                       u32 mss_and_is_end)
-{
-       struct tg3_tx_buffer_desc *txd = &tnapi->tx_ring[entry];
-       int is_end = (mss_and_is_end & 0x1);
-       u32 mss = (mss_and_is_end >> 1);
-       u32 vlan_tag = 0;
-
-       if (is_end)
-               flags |= TXD_FLAG_END;
-       if (flags & TXD_FLAG_VLAN) {
-               vlan_tag = flags >> 16;
-               flags &= 0xffff;
-       }
-       vlan_tag |= (mss << TXD_MSS_SHIFT);
-
-       txd->addr_hi = ((u64) mapping >> 32);
-       txd->addr_lo = ((u64) mapping & 0xffffffff);
-       txd->len_flags = (len << TXD_LEN_SHIFT) | flags;
-       txd->vlan_tag = vlan_tag << TXD_VLAN_TAG_SHIFT;
-}
-
-/* hard_start_xmit for devices that don't have any bugs and
- * support TG3_FLAG_HW_TSO_2 and TG3_FLAG_HW_TSO_3 only.
- */
-static netdev_tx_t tg3_start_xmit(struct sk_buff *skb,
-                                 struct net_device *dev)
-{
-       struct tg3 *tp = netdev_priv(dev);
-       u32 len, entry, base_flags, mss;
-       dma_addr_t mapping;
-       struct tg3_napi *tnapi;
-       struct netdev_queue *txq;
-       unsigned int i, last;
-
-       txq = netdev_get_tx_queue(dev, skb_get_queue_mapping(skb));
-       tnapi = &tp->napi[skb_get_queue_mapping(skb)];
-       if (tg3_flag(tp, ENABLE_TSS))
-               tnapi++;
-
-       /* We are running in BH disabled context with netif_tx_lock
-        * and TX reclaim runs via tp->napi.poll inside of a software
-        * interrupt.  Furthermore, IRQ processing runs lockless so we have
-        * no IRQ context deadlocks to worry about either.  Rejoice!
-        */
-       if (unlikely(tg3_tx_avail(tnapi) <= (skb_shinfo(skb)->nr_frags + 1))) {
-               if (!netif_tx_queue_stopped(txq)) {
-                       netif_tx_stop_queue(txq);
-
-                       /* This is a hard error, log it. */
-                       netdev_err(dev,
-                                  "BUG! Tx Ring full when queue awake!\n");
-               }
-               return NETDEV_TX_BUSY;
-       }
-
-       entry = tnapi->tx_prod;
-       base_flags = 0;
-       mss = skb_shinfo(skb)->gso_size;
-       if (mss) {
-               int tcp_opt_len, ip_tcp_len;
-               u32 hdrlen;
-
-               if (skb_header_cloned(skb) &&
-                   pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) {
-                       dev_kfree_skb(skb);
-                       goto out_unlock;
-               }
-
-               if (skb_is_gso_v6(skb)) {
-                       hdrlen = skb_headlen(skb) - ETH_HLEN;
-               } else {
-                       struct iphdr *iph = ip_hdr(skb);
-
-                       tcp_opt_len = tcp_optlen(skb);
-                       ip_tcp_len = ip_hdrlen(skb) + sizeof(struct tcphdr);
-
-                       iph->check = 0;
-                       iph->tot_len = htons(mss + ip_tcp_len + tcp_opt_len);
-                       hdrlen = ip_tcp_len + tcp_opt_len;
-               }
-
-               if (tg3_flag(tp, HW_TSO_3)) {
-                       mss |= (hdrlen & 0xc) << 12;
-                       if (hdrlen & 0x10)
-                               base_flags |= 0x00000010;
-                       base_flags |= (hdrlen & 0x3e0) << 5;
-               } else
-                       mss |= hdrlen << 9;
-
-               base_flags |= (TXD_FLAG_CPU_PRE_DMA |
-                              TXD_FLAG_CPU_POST_DMA);
-
-               tcp_hdr(skb)->check = 0;
-
-       } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
-               base_flags |= TXD_FLAG_TCPUDP_CSUM;
-       }
-
-       if (vlan_tx_tag_present(skb))
-               base_flags |= (TXD_FLAG_VLAN |
-                              (vlan_tx_tag_get(skb) << 16));
-
-       len = skb_headlen(skb);
-
-       /* Queue skb data, a.k.a. the main skb fragment. */
-       mapping = pci_map_single(tp->pdev, skb->data, len, PCI_DMA_TODEVICE);
-       if (pci_dma_mapping_error(tp->pdev, mapping)) {
-               dev_kfree_skb(skb);
-               goto out_unlock;
-       }
-
-       tnapi->tx_buffers[entry].skb = skb;
-       dma_unmap_addr_set(&tnapi->tx_buffers[entry], mapping, mapping);
-
-       if (tg3_flag(tp, USE_JUMBO_BDFLAG) &&
-           !mss && skb->len > VLAN_ETH_FRAME_LEN)
-               base_flags |= TXD_FLAG_JMB_PKT;
-
-       tg3_set_txd(tnapi, entry, mapping, len, base_flags,
-                   (skb_shinfo(skb)->nr_frags == 0) | (mss << 1));
-
-       entry = NEXT_TX(entry);
-
-       /* Now loop through additional data fragments, and queue them. */
-       if (skb_shinfo(skb)->nr_frags > 0) {
-               last = skb_shinfo(skb)->nr_frags - 1;
-               for (i = 0; i <= last; i++) {
-                       skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
-
-                       len = frag->size;
-                       mapping = pci_map_page(tp->pdev,
-                                              frag->page,
-                                              frag->page_offset,
-                                              len, PCI_DMA_TODEVICE);
-                       if (pci_dma_mapping_error(tp->pdev, mapping))
-                               goto dma_error;
-
-                       tnapi->tx_buffers[entry].skb = NULL;
-                       dma_unmap_addr_set(&tnapi->tx_buffers[entry], mapping,
-                                          mapping);
-
-                       tg3_set_txd(tnapi, entry, mapping, len,
-                                   base_flags, (i == last) | (mss << 1));
-
-                       entry = NEXT_TX(entry);
-               }
-       }
-
-       /* Packets are ready, update Tx producer idx local and on card. */
-       tw32_tx_mbox(tnapi->prodmbox, entry);
-
-       tnapi->tx_prod = entry;
-       if (unlikely(tg3_tx_avail(tnapi) <= (MAX_SKB_FRAGS + 1))) {
-               netif_tx_stop_queue(txq);
-
-               /* netif_tx_stop_queue() must be done before checking
-                * checking tx index in tg3_tx_avail() below, because in
-                * tg3_tx(), we update tx index before checking for
-                * netif_tx_queue_stopped().
-                */
-               smp_mb();
-               if (tg3_tx_avail(tnapi) > TG3_TX_WAKEUP_THRESH(tnapi))
-                       netif_tx_wake_queue(txq);
-       }
-
-out_unlock:
-       mmiowb();
-
-       return NETDEV_TX_OK;
-
-dma_error:
-       last = i;
-       entry = tnapi->tx_prod;
-       tnapi->tx_buffers[entry].skb = NULL;
-       pci_unmap_single(tp->pdev,
-                        dma_unmap_addr(&tnapi->tx_buffers[entry], mapping),
-                        skb_headlen(skb),
-                        PCI_DMA_TODEVICE);
-       for (i = 0; i <= last; i++) {
-               skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
-               entry = NEXT_TX(entry);
-
-               pci_unmap_page(tp->pdev,
-                              dma_unmap_addr(&tnapi->tx_buffers[entry],
-                                             mapping),
-                              frag->size, PCI_DMA_TODEVICE);
-       }
-
-       dev_kfree_skb(skb);
-       return NETDEV_TX_OK;
-}
-
-static netdev_tx_t tg3_start_xmit_dma_bug(struct sk_buff *,
-                                         struct net_device *);
+static netdev_tx_t tg3_start_xmit(struct sk_buff *, struct net_device *);
 
 /* Use GSO to workaround a rare TSO bug that may be triggered when the
  * TSO header is greater than 80 bytes.
@@ -6047,7 +5875,7 @@ static int tg3_tso_bug(struct tg3 *tp, struct sk_buff *skb)
                nskb = segs;
                segs = segs->next;
                nskb->next = NULL;
-               tg3_start_xmit_dma_bug(nskb, tp->dev);
+               tg3_start_xmit(nskb, tp->dev);
        } while (segs);
 
 tg3_tso_bug_end:
@@ -6059,16 +5887,15 @@ tg3_tso_bug_end:
 /* hard_start_xmit for devices that have the 4G bug and/or 40-bit bug and
  * support TG3_FLAG_HW_TSO_1 or firmware TSO only.
  */
-static netdev_tx_t tg3_start_xmit_dma_bug(struct sk_buff *skb,
-                                         struct net_device *dev)
+static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct tg3 *tp = netdev_priv(dev);
        u32 len, entry, base_flags, mss;
-       int would_hit_hwbug;
+       int i = -1, would_hit_hwbug;
        dma_addr_t mapping;
        struct tg3_napi *tnapi;
        struct netdev_queue *txq;
-       unsigned int i, last;
+       unsigned int last;
 
        txq = netdev_get_tx_queue(dev, skb_get_queue_mapping(skb));
        tnapi = &tp->napi[skb_get_queue_mapping(skb)];
@@ -6249,20 +6076,15 @@ static netdev_tx_t tg3_start_xmit_dma_bug(struct sk_buff *skb,
        }
 
        if (would_hit_hwbug) {
-               u32 last_plus_one = entry;
-               u32 start;
-
-               start = entry - 1 - skb_shinfo(skb)->nr_frags;
-               start &= (TG3_TX_RING_SIZE - 1);
+               tg3_skb_error_unmap(tnapi, skb, i);
 
                /* If the workaround fails due to memory/mapping
                 * failure, silently drop this packet.
                 */
-               if (tigon3_dma_hwbug_workaround(tnapi, skb, last_plus_one,
-                                               &start, base_flags, mss))
+               if (tigon3_dma_hwbug_workaround(tnapi, skb, base_flags, mss))
                        goto out_unlock;
 
-               entry = start;
+               entry = NEXT_TX(tnapi->tx_prod);
        }
 
        /* Packets are ready, update Tx producer idx local and on card. */
@@ -6288,27 +6110,48 @@ out_unlock:
        return NETDEV_TX_OK;
 
 dma_error:
-       last = i;
-       entry = tnapi->tx_prod;
-       tnapi->tx_buffers[entry].skb = NULL;
-       pci_unmap_single(tp->pdev,
-                        dma_unmap_addr(&tnapi->tx_buffers[entry], mapping),
-                        skb_headlen(skb),
-                        PCI_DMA_TODEVICE);
-       for (i = 0; i <= last; i++) {
-               skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
-               entry = NEXT_TX(entry);
-
-               pci_unmap_page(tp->pdev,
-                              dma_unmap_addr(&tnapi->tx_buffers[entry],
-                                             mapping),
-                              frag->size, PCI_DMA_TODEVICE);
-       }
-
+       tg3_skb_error_unmap(tnapi, skb, i);
        dev_kfree_skb(skb);
+       tnapi->tx_buffers[tnapi->tx_prod].skb = NULL;
        return NETDEV_TX_OK;
 }
 
+static void tg3_set_loopback(struct net_device *dev, u32 features)
+{
+       struct tg3 *tp = netdev_priv(dev);
+
+       if (features & NETIF_F_LOOPBACK) {
+               if (tp->mac_mode & MAC_MODE_PORT_INT_LPBACK)
+                       return;
+
+               /*
+                * Clear MAC_MODE_HALF_DUPLEX or you won't get packets back in
+                * loopback mode if Half-Duplex mode was negotiated earlier.
+                */
+               tp->mac_mode &= ~MAC_MODE_HALF_DUPLEX;
+
+               /* Enable internal MAC loopback mode */
+               tp->mac_mode |= MAC_MODE_PORT_INT_LPBACK;
+               spin_lock_bh(&tp->lock);
+               tw32(MAC_MODE, tp->mac_mode);
+               netif_carrier_on(tp->dev);
+               spin_unlock_bh(&tp->lock);
+               netdev_info(dev, "Internal MAC loopback mode enabled.\n");
+       } else {
+               if (!(tp->mac_mode & MAC_MODE_PORT_INT_LPBACK))
+                       return;
+
+               /* Disable internal MAC loopback mode */
+               tp->mac_mode &= ~MAC_MODE_PORT_INT_LPBACK;
+               spin_lock_bh(&tp->lock);
+               tw32(MAC_MODE, tp->mac_mode);
+               /* Force link status check */
+               tg3_setup_phy(tp, 1);
+               spin_unlock_bh(&tp->lock);
+               netdev_info(dev, "Internal MAC loopback mode disabled.\n");
+       }
+}
+
 static u32 tg3_fix_features(struct net_device *dev, u32 features)
 {
        struct tg3 *tp = netdev_priv(dev);
@@ -6319,6 +6162,16 @@ static u32 tg3_fix_features(struct net_device *dev, u32 features)
        return features;
 }
 
+static int tg3_set_features(struct net_device *dev, u32 features)
+{
+       u32 changed = dev->features ^ features;
+
+       if ((changed & NETIF_F_LOOPBACK) && netif_running(dev))
+               tg3_set_loopback(dev, features);
+
+       return 0;
+}
+
 static inline void tg3_set_mtu(struct net_device *dev, struct tg3 *tp,
                               int new_mtu)
 {
@@ -8141,6 +7994,22 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
                        tw32(GRC_MODE, grc_mode);
                }
 
+               if (GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_57765_AX) {
+                       u32 grc_mode = tr32(GRC_MODE);
+
+                       /* Access the lower 1K of DL PCIE block registers. */
+                       val = grc_mode & ~GRC_MODE_PCIE_PORT_MASK;
+                       tw32(GRC_MODE, val | GRC_MODE_PCIE_DL_SEL);
+
+                       val = tr32(TG3_PCIE_TLDLPL_PORT +
+                                  TG3_PCIE_DL_LO_FTSMAX);
+                       val &= ~TG3_PCIE_DL_LO_FTSMAX_MSK;
+                       tw32(TG3_PCIE_TLDLPL_PORT + TG3_PCIE_DL_LO_FTSMAX,
+                            val | TG3_PCIE_DL_LO_FTSMAX_VAL);
+
+                       tw32(GRC_MODE, grc_mode);
+               }
+
                val = tr32(TG3_CPMU_LSPD_10MB_CLK);
                val &= ~CPMU_LSPD_10MB_MACCLK_MASK;
                val |= CPMU_LSPD_10MB_MACCLK_6_25;
@@ -8438,7 +8307,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
            tg3_flag(tp, HW_TSO_3))
                rdmac_mode |= RDMAC_MODE_IPV4_LSO_EN;
 
-       if (tg3_flag(tp, HW_TSO_3) ||
+       if (tg3_flag(tp, 57765_PLUS) ||
            GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 ||
            GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780)
                rdmac_mode |= RDMAC_MODE_IPV6_LSO_EN;
@@ -8777,7 +8646,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
        }
 
        if ((tp->phy_flags & TG3_PHYFLG_MII_SERDES) &&
-           (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714)) {
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714) {
                u32 tmp;
 
                tmp = tr32(SERDES_RX_CTRL);
@@ -8928,7 +8797,9 @@ static void tg3_periodic_fetch_stats(struct tg3 *tp)
        TG3_STAT_ADD32(&sp->rx_undersize_packets, MAC_RX_STATS_UNDERSIZE);
 
        TG3_STAT_ADD32(&sp->rxbds_empty, RCVLPC_NO_RCV_BD_CNT);
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717) {
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717 &&
+           tp->pci_chip_rev_id != CHIPREV_ID_5719_A0 &&
+           tp->pci_chip_rev_id != CHIPREV_ID_5720_A0) {
                TG3_STAT_ADD32(&sp->rx_discards, RCVLPC_IN_DISCARDS_CNT);
        } else {
                u32 val = tr32(HOSTCC_FLOW_ATTN);
@@ -8979,11 +8850,8 @@ static void tg3_timer(unsigned long __opaque)
                if (tg3_flag(tp, 5705_PLUS))
                        tg3_periodic_fetch_stats(tp);
 
-               if (tp->setlpicnt && !--tp->setlpicnt) {
-                       u32 val = tr32(TG3_CPMU_EEE_MODE);
-                       tw32(TG3_CPMU_EEE_MODE,
-                            val | TG3_CPMU_EEEMD_LPI_ENABLE);
-               }
+               if (tp->setlpicnt && !--tp->setlpicnt)
+                       tg3_phy_eee_enable(tp);
 
                if (tg3_flag(tp, USE_LINKCHG_REG)) {
                        u32 mac_stat;
@@ -9485,6 +9353,13 @@ static int tg3_open(struct net_device *dev)
 
        netif_tx_start_all_queues(dev);
 
+       /*
+        * Reset loopback feature if it was turned on while the device was down
+        * make sure that it's installed properly now.
+        */
+       if (dev->features & NETIF_F_LOOPBACK)
+               tg3_set_loopback(dev, dev->features);
+
        return 0;
 
 err_out3:
@@ -9674,6 +9549,8 @@ static struct tg3_ethtool_stats *tg3_get_estats(struct tg3 *tp)
        ESTAT_ADD(nic_avoided_irqs);
        ESTAT_ADD(nic_tx_threshold_hit);
 
+       ESTAT_ADD(mbuf_lwm_thresh_hit);
+
        return estats;
 }
 
@@ -10025,10 +9902,10 @@ static int tg3_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 
        cmd->advertising = tp->link_config.advertising;
        if (netif_running(dev)) {
-               cmd->speed = tp->link_config.active_speed;
+               ethtool_cmd_speed_set(cmd, tp->link_config.active_speed);
                cmd->duplex = tp->link_config.active_duplex;
        } else {
-               cmd->speed = SPEED_INVALID;
+               ethtool_cmd_speed_set(cmd, SPEED_INVALID);
                cmd->duplex = DUPLEX_INVALID;
        }
        cmd->phy_address = tp->phy_addr;
@@ -11323,7 +11200,7 @@ static int tg3_run_loopback(struct tg3 *tp, u32 pktsz, int loopback_mode)
                        }
                } else if ((desc->type_flags & RXD_FLAG_TCPUDP_CSUM) &&
                           (desc->ip_tcp_csum & RXD_TCPCSUM_MASK)
-                           >> RXD_TCPCSUM_SHIFT == 0xffff) {
+                           >> RXD_TCPCSUM_SHIFT != 0xffff) {
                        goto out;
                }
 
@@ -11761,7 +11638,7 @@ static void __devinit tg3_get_nvram_info(struct tg3 *tp)
                tw32(NVRAM_CFG1, nvcfg1);
        }
 
-       if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) ||
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 ||
            tg3_flag(tp, 5780_CLASS)) {
                switch (nvcfg1 & NVRAM_CFG1_VENDOR_MASK) {
                case FLASH_VENDOR_ATMEL_FLASH_BUFFERED:
@@ -12747,8 +12624,10 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
                if (val & VCPU_CFGSHDW_ASPM_DBNC)
                        tg3_flag_set(tp, ASPM_WORKAROUND);
                if ((val & VCPU_CFGSHDW_WOL_ENABLE) &&
-                   (val & VCPU_CFGSHDW_WOL_MAGPKT))
+                   (val & VCPU_CFGSHDW_WOL_MAGPKT)) {
                        tg3_flag_set(tp, WOL_ENABLE);
+                       device_set_wakeup_enable(&tp->pdev->dev, true);
+               }
                goto done;
        }
 
@@ -12763,9 +12642,9 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
 
                tg3_read_mem(tp, NIC_SRAM_DATA_VER, &ver);
                ver >>= NIC_SRAM_DATA_VER_SHIFT;
-               if ((GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700) &&
-                   (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) &&
-                   (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5703) &&
+               if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 &&
+                   GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701 &&
+                   GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5703 &&
                    (ver > 0) && (ver < 0x100))
                        tg3_read_mem(tp, NIC_SRAM_DATA_CFG_2, &cfg2);
 
@@ -12881,8 +12760,10 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
                        tg3_flag_clear(tp, WOL_CAP);
 
                if (tg3_flag(tp, WOL_CAP) &&
-                   (nic_cfg & NIC_SRAM_DATA_CFG_WOL_ENABLE))
+                   (nic_cfg & NIC_SRAM_DATA_CFG_WOL_ENABLE)) {
                        tg3_flag_set(tp, WOL_ENABLE);
+                       device_set_wakeup_enable(&tp->pdev->dev, true);
+               }
 
                if (cfg2 & (1 << 17))
                        tp->phy_flags |= TG3_PHYFLG_CAPACITIVE_COUPLING;
@@ -13076,7 +12957,7 @@ static int __devinit tg3_phy_probe(struct tg3 *tp)
        if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES) &&
            !tg3_flag(tp, ENABLE_APE) &&
            !tg3_flag(tp, ENABLE_ASF)) {
-               u32 bmsr, adv_reg, tg3_ctrl, mask;
+               u32 bmsr, mask;
 
                tg3_readphy(tp, MII_BMSR, &bmsr);
                if (!tg3_readphy(tp, MII_BMSR, &bmsr) &&
@@ -13087,36 +12968,18 @@ static int __devinit tg3_phy_probe(struct tg3 *tp)
                if (err)
                        return err;
 
-               adv_reg = (ADVERTISE_10HALF | ADVERTISE_10FULL |
-                          ADVERTISE_100HALF | ADVERTISE_100FULL |
-                          ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP);
-               tg3_ctrl = 0;
-               if (!(tp->phy_flags & TG3_PHYFLG_10_100_ONLY)) {
-                       tg3_ctrl = (MII_TG3_CTRL_ADV_1000_HALF |
-                                   MII_TG3_CTRL_ADV_1000_FULL);
-                       if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 ||
-                           tp->pci_chip_rev_id == CHIPREV_ID_5701_B0)
-                               tg3_ctrl |= (MII_TG3_CTRL_AS_MASTER |
-                                            MII_TG3_CTRL_ENABLE_AS_MASTER);
-               }
+               tg3_phy_set_wirespeed(tp);
 
                mask = (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |
                        ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full |
                        ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full);
                if (!tg3_copper_is_advertising_all(tp, mask)) {
-                       tg3_writephy(tp, MII_ADVERTISE, adv_reg);
-
-                       if (!(tp->phy_flags & TG3_PHYFLG_10_100_ONLY))
-                               tg3_writephy(tp, MII_TG3_CTRL, tg3_ctrl);
+                       tg3_phy_autoneg_cfg(tp, tp->link_config.advertising,
+                                           tp->link_config.flowctrl);
 
                        tg3_writephy(tp, MII_BMCR,
                                     BMCR_ANENABLE | BMCR_ANRESTART);
                }
-               tg3_phy_set_wirespeed(tp);
-
-               tg3_writephy(tp, MII_ADVERTISE, adv_reg);
-               if (!(tp->phy_flags & TG3_PHYFLG_10_100_ONLY))
-                       tg3_writephy(tp, MII_TG3_CTRL, tg3_ctrl);
        }
 
 skip_phy_reset:
@@ -13637,7 +13500,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
                }
        }
 
-       if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701)) {
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) {
                static struct tg3_dev_id {
                        u32     vendor;
                        u32     device;
@@ -13737,23 +13600,10 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
            tg3_flag(tp, 5780_CLASS))
                tg3_flag_set(tp, 5750_PLUS);
 
-       if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) ||
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ||
            tg3_flag(tp, 5750_PLUS))
                tg3_flag_set(tp, 5705_PLUS);
 
-       /* 5700 B0 chips do not support checksumming correctly due
-        * to hardware bugs.
-        */
-       if (tp->pci_chip_rev_id != CHIPREV_ID_5700_B0) {
-               u32 features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_RXCSUM;
-
-               if (tg3_flag(tp, 5755_PLUS))
-                       features |= NETIF_F_IPV6_CSUM;
-               tp->dev->features |= features;
-               tp->dev->hw_features |= features;
-               tp->dev->vlan_features |= features;
-       }
-
        /* Determine TSO capabilities */
        if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719)
                ; /* Do nothing. HW bug. */
@@ -13778,6 +13628,21 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
                        tp->fw_needed = FIRMWARE_TG3TSO;
        }
 
+       /* Selectively allow TSO based on operating conditions */
+       if (tg3_flag(tp, HW_TSO_1) ||
+           tg3_flag(tp, HW_TSO_2) ||
+           tg3_flag(tp, HW_TSO_3) ||
+           (tp->fw_needed && !tg3_flag(tp, ENABLE_ASF)))
+               tg3_flag_set(tp, TSO_CAPABLE);
+       else {
+               tg3_flag_clear(tp, TSO_CAPABLE);
+               tg3_flag_clear(tp, TSO_BUG);
+               tp->fw_needed = NULL;
+       }
+
+       if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0)
+               tp->fw_needed = FIRMWARE_TG3;
+
        tp->irq_max = 1;
 
        if (tg3_flag(tp, 5750_PLUS)) {
@@ -13800,14 +13665,15 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
                }
        }
 
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
-           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 ||
-           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
+       /* All chips can get confused if TX buffers
+        * straddle the 4GB address boundary.
+        */
+       tg3_flag_set(tp, 4G_DMA_BNDRY_BUG);
+
+       if (tg3_flag(tp, 5755_PLUS))
                tg3_flag_set(tp, SHORT_DMA_BUG);
-       else if (!tg3_flag(tp, 5755_PLUS)) {
-               tg3_flag_set(tp, 4G_DMA_BNDRY_BUG);
+       else
                tg3_flag_set(tp, 40BIT_DMA_LIMIT_BUG);
-       }
 
        if (tg3_flag(tp, 5717_PLUS))
                tg3_flag_set(tp, LRG_PROD_RING_CAP);
@@ -13843,6 +13709,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
                if (lnkctl & PCI_EXP_LNKCTL_CLKREQ_EN) {
                        if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
                                tg3_flag_clear(tp, HW_TSO_2);
+                               tg3_flag_clear(tp, TSO_CAPABLE);
                        if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
                            GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
                            tp->pci_chip_rev_id == CHIPREV_ID_57780_A0 ||
@@ -14026,7 +13893,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
         * It is also used as eeprom write protect on LOMs.
         */
        tp->grc_local_ctrl = GRC_LCLCTRL_INT_ON_ATTN | GRC_LCLCTRL_AUTO_SEEPROM;
-       if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) ||
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
            tg3_flag(tp, EEPROM_WRITE_PROT))
                tp->grc_local_ctrl |= (GRC_LCLCTRL_GPIO_OE1 |
                                       GRC_LCLCTRL_GPIO_OUTPUT1);
@@ -14078,8 +13945,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
                tp->phy_flags |= TG3_PHYFLG_IS_FET;
 
        /* A few boards don't want Ethernet@WireSpeed phy feature */
-       if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) ||
-           ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) &&
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
+           (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 &&
             (tp->pci_chip_rev_id != CHIPREV_ID_5705_A0) &&
             (tp->pci_chip_rev_id != CHIPREV_ID_5705_A1)) ||
            (tp->phy_flags & TG3_PHYFLG_IS_FET) ||
@@ -14199,7 +14066,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
                tg3_flag_set(tp, IS_5788);
 
        if (!tg3_flag(tp, IS_5788) &&
-           (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700))
+           GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700)
                tg3_flag_set(tp, TAGGED_STATUS);
        if (tg3_flag(tp, TAGGED_STATUS)) {
                tp->coalesce_mode |= (HOSTCC_MODE_CLRTICK_RXBD |
@@ -14350,7 +14217,7 @@ static int __devinit tg3_get_device_address(struct tg3 *tp)
 #endif
 
        mac_offset = 0x7c;
-       if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) ||
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 ||
            tg3_flag(tp, 5780_CLASS)) {
                if (tr32(TG3PCI_DUAL_MAC_CTRL) & DUAL_MAC_CTRL_ID)
                        mac_offset = 0xcc;
@@ -15029,22 +14896,7 @@ static const struct net_device_ops tg3_netdev_ops = {
        .ndo_tx_timeout         = tg3_tx_timeout,
        .ndo_change_mtu         = tg3_change_mtu,
        .ndo_fix_features       = tg3_fix_features,
-#ifdef CONFIG_NET_POLL_CONTROLLER
-       .ndo_poll_controller    = tg3_poll_controller,
-#endif
-};
-
-static const struct net_device_ops tg3_netdev_ops_dma_bug = {
-       .ndo_open               = tg3_open,
-       .ndo_stop               = tg3_close,
-       .ndo_start_xmit         = tg3_start_xmit_dma_bug,
-       .ndo_get_stats64        = tg3_get_stats64,
-       .ndo_validate_addr      = eth_validate_addr,
-       .ndo_set_multicast_list = tg3_set_rx_mode,
-       .ndo_set_mac_address    = tg3_set_mac_addr,
-       .ndo_do_ioctl           = tg3_ioctl,
-       .ndo_tx_timeout         = tg3_tx_timeout,
-       .ndo_change_mtu         = tg3_change_mtu,
+       .ndo_set_features       = tg3_set_features,
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller    = tg3_poll_controller,
 #endif
@@ -15059,7 +14911,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
        u32 sndmbx, rcvmbx, intmbx;
        char str[40];
        u64 dma_mask, persist_dma_mask;
-       u32 hw_features = 0;
+       u32 features = 0;
 
        printk_once(KERN_INFO "%s\n", version);
 
@@ -15095,8 +14947,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
 
        SET_NETDEV_DEV(dev, &pdev->dev);
 
-       dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
-
        tp = netdev_priv(dev);
        tp->pdev = pdev;
        tp->dev = dev;
@@ -15146,6 +14996,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
 
        dev->ethtool_ops = &tg3_ethtool_ops;
        dev->watchdog_timeo = TG3_TX_TIMEOUT;
+       dev->netdev_ops = &tg3_netdev_ops;
        dev->irq = pdev->irq;
 
        err = tg3_get_invariants(tp);
@@ -15155,12 +15006,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
                goto err_out_iounmap;
        }
 
-       if (tg3_flag(tp, 5755_PLUS) && !tg3_flag(tp, 5717_PLUS))
-               dev->netdev_ops = &tg3_netdev_ops;
-       else
-               dev->netdev_ops = &tg3_netdev_ops_dma_bug;
-
-
        /* The EPB bridge inside 5714, 5715, and 5780 and any
         * device behind the EPB cannot support DMA addresses > 40-bit.
         * On 64-bit systems with IOMMU, use 40-bit dma_mask.
@@ -15181,7 +15026,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
        if (dma_mask > DMA_BIT_MASK(32)) {
                err = pci_set_dma_mask(pdev, dma_mask);
                if (!err) {
-                       dev->features |= NETIF_F_HIGHDMA;
+                       features |= NETIF_F_HIGHDMA;
                        err = pci_set_consistent_dma_mask(pdev,
                                                          persist_dma_mask);
                        if (err < 0) {
@@ -15202,20 +15047,17 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
 
        tg3_init_bufmgr_config(tp);
 
-       /* Selectively allow TSO based on operating conditions */
-       if ((tg3_flag(tp, HW_TSO_1) ||
-            tg3_flag(tp, HW_TSO_2) ||
-            tg3_flag(tp, HW_TSO_3)) ||
-           (tp->fw_needed && !tg3_flag(tp, ENABLE_ASF)))
-               tg3_flag_set(tp, TSO_CAPABLE);
-       else {
-               tg3_flag_clear(tp, TSO_CAPABLE);
-               tg3_flag_clear(tp, TSO_BUG);
-               tp->fw_needed = NULL;
-       }
+       features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
 
-       if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0)
-               tp->fw_needed = FIRMWARE_TG3;
+       /* 5700 B0 chips do not support checksumming correctly due
+        * to hardware bugs.
+        */
+       if (tp->pci_chip_rev_id != CHIPREV_ID_5700_B0) {
+               features |= NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_RXCSUM;
+
+               if (tg3_flag(tp, 5755_PLUS))
+                       features |= NETIF_F_IPV6_CSUM;
+       }
 
        /* TSO is on by default on chips that support hardware TSO.
         * Firmware TSO on older chips gives lower performance, so it
@@ -15224,23 +15066,34 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
        if ((tg3_flag(tp, HW_TSO_1) ||
             tg3_flag(tp, HW_TSO_2) ||
             tg3_flag(tp, HW_TSO_3)) &&
-           (dev->features & NETIF_F_IP_CSUM))
-               hw_features |= NETIF_F_TSO;
+           (features & NETIF_F_IP_CSUM))
+               features |= NETIF_F_TSO;
        if (tg3_flag(tp, HW_TSO_2) || tg3_flag(tp, HW_TSO_3)) {
-               if (dev->features & NETIF_F_IPV6_CSUM)
-                       hw_features |= NETIF_F_TSO6;
+               if (features & NETIF_F_IPV6_CSUM)
+                       features |= NETIF_F_TSO6;
                if (tg3_flag(tp, HW_TSO_3) ||
                    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
                    (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 &&
                     GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5784_AX) ||
                    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 ||
                    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780)
-                       hw_features |= NETIF_F_TSO_ECN;
+                       features |= NETIF_F_TSO_ECN;
        }
 
-       dev->hw_features |= hw_features;
-       dev->features |= hw_features;
-       dev->vlan_features |= hw_features;
+       dev->features |= features;
+       dev->vlan_features |= features;
+
+       /*
+        * Add loopback capability only for a subset of devices that support
+        * MAC-LOOPBACK. Eventually this need to be enhanced to allow INT-PHY
+        * loopback for the remaining devices.
+        */
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5780 &&
+           !tg3_flag(tp, CPMU_PRESENT))
+               /* Add the loopback capability */
+               features |= NETIF_F_LOOPBACK;
+
+       dev->hw_features |= features;
 
        if (tp->pci_chip_rev_id == CHIPREV_ID_5705_A1 &&
            !tg3_flag(tp, TSO_CAPABLE) &&