]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - drivers/net/tg3.c
tg3: Fix single MSI-X vector coalescing
[net-next-2.6.git] / drivers / net / tg3.c
index 86f8798a88e29c7cc4aa19b3d0b3a248ed431ec5..57dba794d31eeb589c4377aa13e9e94a65125fe9 100644 (file)
@@ -67,8 +67,8 @@
 #include "tg3.h"
 
 #define DRV_MODULE_NAME                "tg3"
-#define DRV_MODULE_VERSION     "3.110"
-#define DRV_MODULE_RELDATE     "April 9, 2010"
+#define DRV_MODULE_VERSION     "3.111"
+#define DRV_MODULE_RELDATE     "June 5, 2010"
 
 #define TG3_DEF_MAC_MODE       0
 #define TG3_DEF_RX_MODE                0
 #define TG3_RX_JMB_BUFF_RING_SIZE \
        (sizeof(struct ring_info) * TG3_RX_JUMBO_RING_SIZE)
 
-#define TG3_RSS_MIN_NUM_MSIX_VECS      2
-
 /* Due to a hardware bug, the 5701 can only DMA to memory addresses
  * that are at least dword aligned when used in PCIX mode.  The driver
  * works around this bug by double copying the packet.  This workaround
@@ -272,6 +270,7 @@ static DEFINE_PCI_DEVICE_TABLE(tg3_pci_tbl) = {
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57765)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57791)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57795)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5719)},
        {PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9DXX)},
        {PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9MXX)},
        {PCI_DEVICE(PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1000)},
@@ -1086,14 +1085,11 @@ static int tg3_mdio_init(struct tg3 *tp)
        u32 reg;
        struct phy_device *phydev;
 
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) {
-               u32 funcnum, is_serdes;
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) {
+               u32 is_serdes;
 
-               funcnum = tr32(TG3_CPMU_STATUS) & TG3_CPMU_STATUS_PCIE_FUNC;
-               if (funcnum)
-                       tp->phy_addr = 2;
-               else
-                       tp->phy_addr = 1;
+               tp->phy_addr = PCI_FUNC(tp->pdev->devfn) + 1;
 
                if (tp->pci_chip_rev_id != CHIPREV_ID_5717_A0)
                        is_serdes = tr32(SG_DIG_STATUS) & SG_DIG_IS_SERDES;
@@ -1606,7 +1602,8 @@ static void tg3_phy_toggle_apd(struct tg3 *tp, bool enable)
        u32 reg;
 
        if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) ||
-               (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 &&
+           ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
+             GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) &&
             (tp->tg3_flags2 & TG3_FLG2_MII_SERDES)))
                return;
 
@@ -1981,7 +1978,8 @@ static int tg3_phy_reset(struct tg3 *tp)
                }
        }
 
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 &&
+       if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
+            GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) &&
            (tp->tg3_flags2 & TG3_FLG2_MII_SERDES))
                return 0;
 
@@ -2066,6 +2064,7 @@ static void tg3_frob_aux_power(struct tg3 *tp)
 
        /* The GPIOs do something completely different on 57765. */
        if ((tp->tg3_flags2 & TG3_FLG2_IS_NIC) == 0 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 ||
            GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765)
                return;
 
@@ -4208,6 +4207,8 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset)
                                        current_duplex = DUPLEX_FULL;
                                else
                                        current_duplex = DUPLEX_HALF;
+                       } else if (!(tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) {
+                               /* Link is up via parallel detect */
                        } else {
                                current_link_up = 0;
                        }
@@ -7087,6 +7088,7 @@ static int tg3_chip_reset(struct tg3 *tp)
            tp->pci_chip_rev_id != CHIPREV_ID_5750_A0 &&
            GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785 &&
            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) {
                val = tr32(0x7c00);
 
@@ -7445,7 +7447,7 @@ static void __tg3_set_coalesce(struct tg3 *tp, struct ethtool_coalesce *ec)
                tw32(HOSTCC_TXCOAL_MAXF_INT, 0);
        }
 
-       if (!(tp->tg3_flags2 & TG3_FLG2_USING_MSIX)) {
+       if (!(tp->tg3_flags3 & TG3_FLG3_ENABLE_RSS)) {
                tw32(HOSTCC_RXCOL_TICKS, ec->rx_coalesce_usecs);
                tw32(HOSTCC_RXMAX_FRAMES, ec->rx_max_coalesced_frames);
                tw32(HOSTCC_RXCOAL_MAXF_INT, ec->rx_max_coalesced_frames_irq);
@@ -7522,7 +7524,8 @@ static void tg3_rings_reset(struct tg3 *tp)
 
 
        /* Disable all receive return rings but the first. */
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717)
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719)
                limit = NIC_SRAM_RCV_RET_RCB + TG3_BDINFO_SIZE * 17;
        else if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS))
                limit = NIC_SRAM_RCV_RET_RCB + TG3_BDINFO_SIZE * 16;
@@ -7760,6 +7763,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
                return err;
 
        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_57765) {
                val = tr32(TG3PCI_DMA_RW_CTRL) &
                      ~DMA_RWCTRL_DIS_CACHE_ALIGNMENT;
@@ -7888,7 +7892,8 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
             ((u64) tpr->rx_std_mapping >> 32));
        tw32(RCVDBDI_STD_BD + TG3_BDINFO_HOST_ADDR + TG3_64BIT_REG_LOW,
             ((u64) tpr->rx_std_mapping & 0xffffffff));
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717)
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717 &&
+           GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5719)
                tw32(RCVDBDI_STD_BD + TG3_BDINFO_NIC_ADDR,
                     NIC_SRAM_RX_BUFFER_DESC);
 
@@ -7913,7 +7918,8 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
                        tw32(RCVDBDI_JUMBO_BD + TG3_BDINFO_MAXLEN_FLAGS,
                             (RX_JUMBO_MAX_SIZE << BDINFO_FLAGS_MAXLEN_SHIFT) |
                             BDINFO_FLAGS_USE_EXT_RECV);
-                       if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717)
+                       if (!(tp->tg3_flags3 & TG3_FLG3_USE_JUMBO_BDFLAG) ||
+                           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765)
                                tw32(RCVDBDI_JUMBO_BD + TG3_BDINFO_NIC_ADDR,
                                     NIC_SRAM_RX_JUMBO_BUFFER_DESC);
                } else {
@@ -7922,6 +7928,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
                }
 
                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_57765)
                        val = (RX_STD_MAX_SIZE_5705 << BDINFO_FLAGS_MAXLEN_SHIFT) |
                              (TG3_RX_STD_DMA_SZ << 2);
@@ -7940,6 +7947,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
        tw32_rx_mbox(TG3_RX_JMB_PROD_IDX_REG, tpr->rx_jmb_prod_idx);
 
        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_57765) {
                tw32(STD_REPLENISH_LWM, 32);
                tw32(JMB_REPLENISH_LWM, 16);
@@ -7975,7 +7983,8 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
                      RDMAC_MODE_FIFOURUN_ENAB | RDMAC_MODE_FIFOOREAD_ENAB |
                      RDMAC_MODE_LNGREAD_ENAB);
 
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717)
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719)
                rdmac_mode |= RDMAC_MODE_MULT_DMA_RD_DIS;
 
        if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
@@ -8533,8 +8542,10 @@ static void tg3_timer(unsigned long __opaque)
                                }
                                tg3_setup_phy(tp, 0);
                        }
-               } else if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES)
+               } else if ((tp->tg3_flags2 & TG3_FLG2_MII_SERDES) &&
+                          !(tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) {
                        tg3_serdes_parallel_detect(tp);
+               }
 
                tp->timer_counter = tp->timer_multiplier;
        }
@@ -8628,6 +8639,7 @@ static int tg3_test_interrupt(struct tg3 *tp)
         * observable way to know whether the interrupt was delivered.
         */
        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_57765) &&
            (tp->tg3_flags2 & TG3_FLG2_USING_MSI)) {
                val = tr32(MSGINT_MODE) | MSGINT_MODE_ONE_SHOT_DISABLE;
@@ -8672,6 +8684,7 @@ static int tg3_test_interrupt(struct tg3 *tp)
        if (intr_ok) {
                /* Reenable MSI one shot mode. */
                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_57765) &&
                    (tp->tg3_flags2 & TG3_FLG2_USING_MSI)) {
                        val = tr32(MSGINT_MODE) & ~MSGINT_MODE_ONE_SHOT_DISABLE;
@@ -8797,9 +8810,9 @@ static bool tg3_enable_msix(struct tg3 *tp)
        }
 
        rc = pci_enable_msix(tp->pdev, msix_ent, tp->irq_cnt);
-       if (rc != 0) {
-               if (rc < TG3_RSS_MIN_NUM_MSIX_VECS)
-                       return false;
+       if (rc < 0) {
+               return false;
+       } else if (rc != 0) {
                if (pci_enable_msix(tp->pdev, msix_ent, rc))
                        return false;
                netdev_notice(tp->dev, "Requested %d MSI-X vectors, received %d\n",
@@ -8807,16 +8820,19 @@ static bool tg3_enable_msix(struct tg3 *tp)
                tp->irq_cnt = rc;
        }
 
-       tp->tg3_flags3 |= TG3_FLG3_ENABLE_RSS;
-
        for (i = 0; i < tp->irq_max; i++)
                tp->napi[i].irq_vec = msix_ent[i].vector;
 
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) {
-               tp->tg3_flags3 |= TG3_FLG3_ENABLE_TSS;
-               tp->dev->real_num_tx_queues = tp->irq_cnt - 1;
-       } else
-               tp->dev->real_num_tx_queues = 1;
+       tp->dev->real_num_tx_queues = 1;
+       if (tp->irq_cnt > 1) {
+               tp->tg3_flags3 |= TG3_FLG3_ENABLE_RSS;
+
+               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
+                   GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) {
+                       tp->tg3_flags3 |= TG3_FLG3_ENABLE_TSS;
+                       tp->dev->real_num_tx_queues = tp->irq_cnt - 1;
+               }
+       }
 
        return true;
 }
@@ -8965,6 +8981,7 @@ static int tg3_open(struct net_device *dev)
                }
 
                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_57765 &&
                    (tp->tg3_flags2 & TG3_FLG2_USING_MSI) &&
                    (tp->tg3_flags2 & TG3_FLG2_1SHOT_MSI)) {
@@ -9004,7 +9021,8 @@ err_out1:
        return err;
 }
 
-static struct net_device_stats *tg3_get_stats(struct net_device *);
+static struct rtnl_link_stats64 *tg3_get_stats64(struct net_device *,
+                                                struct rtnl_link_stats64 *);
 static struct tg3_ethtool_stats *tg3_get_estats(struct tg3 *);
 
 static int tg3_close(struct net_device *dev)
@@ -9038,8 +9056,8 @@ static int tg3_close(struct net_device *dev)
 
        tg3_ints_fini(tp);
 
-       memcpy(&tp->net_stats_prev, tg3_get_stats(tp->dev),
-              sizeof(tp->net_stats_prev));
+       tg3_get_stats64(tp->dev, &tp->net_stats_prev);
+
        memcpy(&tp->estats_prev, tg3_get_estats(tp),
               sizeof(tp->estats_prev));
 
@@ -9052,24 +9070,12 @@ static int tg3_close(struct net_device *dev)
        return 0;
 }
 
-static inline unsigned long get_stat64(tg3_stat64_t *val)
-{
-       unsigned long ret;
-
-#if (BITS_PER_LONG == 32)
-       ret = val->low;
-#else
-       ret = ((u64)val->high << 32) | ((u64)val->low);
-#endif
-       return ret;
-}
-
-static inline u64 get_estat64(tg3_stat64_t *val)
+static inline u64 get_stat64(tg3_stat64_t *val)
 {
        return ((u64)val->high << 32) | ((u64)val->low);
 }
 
-static unsigned long calc_crc_errors(struct tg3 *tp)
+static u64 calc_crc_errors(struct tg3 *tp)
 {
        struct tg3_hw_stats *hw_stats = tp->hw_stats;
 
@@ -9097,7 +9103,7 @@ static unsigned long calc_crc_errors(struct tg3 *tp)
 
 #define ESTAT_ADD(member) \
        estats->member =        old_estats->member + \
-                               get_estat64(&hw_stats->member)
+                               get_stat64(&hw_stats->member)
 
 static struct tg3_ethtool_stats *tg3_get_estats(struct tg3 *tp)
 {
@@ -9187,11 +9193,11 @@ static struct tg3_ethtool_stats *tg3_get_estats(struct tg3 *tp)
        return estats;
 }
 
-static struct net_device_stats *tg3_get_stats(struct net_device *dev)
+static struct rtnl_link_stats64 *tg3_get_stats64(struct net_device *dev,
+                                                struct rtnl_link_stats64 *stats)
 {
        struct tg3 *tp = netdev_priv(dev);
-       struct net_device_stats *stats = &tp->net_stats;
-       struct net_device_stats *old_stats = &tp->net_stats_prev;
+       struct rtnl_link_stats64 *old_stats = &tp->net_stats_prev;
        struct tg3_hw_stats *hw_stats = tp->hw_stats;
 
        if (!hw_stats)
@@ -10576,7 +10582,8 @@ static int tg3_test_memory(struct tg3 *tp)
        int err = 0;
        int i;
 
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717)
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719)
                mem_tbl = mem_tbl_5717;
        else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765)
                mem_tbl = mem_tbl_57765;
@@ -11656,7 +11663,8 @@ static void __devinit tg3_nvram_init(struct tg3 *tp)
                else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 ||
                         GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765)
                        tg3_get_57780_nvram_info(tp);
-               else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717)
+               else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
+                        GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719)
                        tg3_get_5717_nvram_info(tp);
                else
                        tg3_get_nvram_info(tp);
@@ -12092,11 +12100,10 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
 
                tp->phy_id = eeprom_phy_id;
                if (eeprom_phy_serdes) {
-                       if ((tp->tg3_flags2 & TG3_FLG2_5780_CLASS) ||
-                           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717)
-                               tp->tg3_flags2 |= TG3_FLG2_MII_SERDES;
-                       else
+                       if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS))
                                tp->tg3_flags2 |= TG3_FLG2_PHY_SERDES;
+                       else
+                               tp->tg3_flags2 |= TG3_FLG2_MII_SERDES;
                }
 
                if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS)
@@ -12782,6 +12789,13 @@ done:
 
 static struct pci_dev * __devinit tg3_find_peer(struct tg3 *);
 
+static void inline vlan_features_add(struct net_device *dev, unsigned long flags)
+{
+#if TG3_VLAN_TAG_USED
+       dev->vlan_features |= flags;
+#endif
+}
+
 static int __devinit tg3_get_invariants(struct tg3 *tp)
 {
        static struct pci_device_id write_reorder_chipsets[] = {
@@ -12826,7 +12840,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
 
                if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717 ||
                    tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718 ||
-                   tp->pdev->device == TG3PCI_DEVICE_TIGON3_5724)
+                   tp->pdev->device == TG3PCI_DEVICE_TIGON3_5724 ||
+                   tp->pdev->device == TG3PCI_DEVICE_TIGON3_5719)
                        pci_read_config_dword(tp->pdev,
                                              TG3PCI_GEN2_PRODID_ASICREV,
                                              &prod_id_asic_rev);
@@ -12992,6 +13007,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
            GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 ||
            GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 ||
            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)
                tp->tg3_flags3 |= TG3_FLG3_5755_PLUS;
 
@@ -13012,15 +13028,18 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
        if (tp->pci_chip_rev_id == CHIPREV_ID_5700_B0)
                tp->tg3_flags |= TG3_FLAG_BROKEN_CHECKSUMS;
        else {
+               unsigned long features = NETIF_F_IP_CSUM | NETIF_F_SG | NETIF_F_GRO;
+
                tp->tg3_flags |= TG3_FLAG_RX_CHECKSUMS;
-               tp->dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
                if (tp->tg3_flags3 & TG3_FLG3_5755_PLUS)
-                       tp->dev->features |= NETIF_F_IPV6_CSUM;
-               tp->dev->features |= NETIF_F_GRO;
+                       features |= NETIF_F_IPV6_CSUM;
+               tp->dev->features |= features;
+               vlan_features_add(tp->dev, features);
        }
 
        /* Determine TSO capabilities */
        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_57765)
                tp->tg3_flags2 |= TG3_FLG2_HW_TSO_3;
        else if ((tp->tg3_flags3 & TG3_FLG3_5755_PLUS) ||
@@ -13058,6 +13077,7 @@ 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_57765) {
                        tp->tg3_flags |= TG3_FLAG_SUPPORT_MSIX;
                        tp->irq_max = TG3_IRQ_MAX_VECS;
@@ -13065,6 +13085,7 @@ 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)
                tp->tg3_flags3 |= TG3_FLG3_SHORT_DMA_BUG;
        else if (!(tp->tg3_flags3 & TG3_FLG3_5755_PLUS)) {
@@ -13073,6 +13094,7 @@ 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_57765)
                tp->tg3_flags3 |= TG3_FLG3_USE_JUMBO_BDFLAG;
 
@@ -13275,6 +13297,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
            GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 ||
            GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 ||
            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)
                tp->tg3_flags |= TG3_FLAG_CPMU_PRESENT;
 
@@ -13355,6 +13378,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
            GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785 &&
            GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_57780 &&
            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) {
                if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
                    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
@@ -13603,9 +13627,12 @@ static int __devinit tg3_get_device_address(struct tg3 *tp)
                        tw32_f(NVRAM_CMD, NVRAM_CMD_RESET);
                else
                        tg3_nvram_unlock(tp);
-       } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) {
-               if (tr32(TG3_CPMU_STATUS) & TG3_CPMU_STATUS_PCIE_FUNC)
+       } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
+                  GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) {
+               if (PCI_FUNC(tp->pdev->devfn) & 1)
                        mac_offset = 0xcc;
+               if (PCI_FUNC(tp->pdev->devfn) > 1)
+                       mac_offset += 0x18c;
        } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
                mac_offset = 0x10;
 
@@ -13691,6 +13718,7 @@ static u32 __devinit tg3_calc_dma_bndry(struct tg3 *tp, u32 val)
 #endif
 
        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_57765) {
                val = goal ? 0 : DMA_RWCTRL_DIS_CACHE_ALIGNMENT;
                goto out;
@@ -13903,6 +13931,7 @@ static int __devinit tg3_test_dma(struct tg3 *tp)
        tp->dma_rwctrl = tg3_calc_dma_bndry(tp, tp->dma_rwctrl);
 
        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_57765)
                goto out;
 
@@ -14102,6 +14131,7 @@ static void __devinit tg3_init_link_config(struct tg3 *tp)
 static void __devinit tg3_init_bufmgr_config(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_57765) {
                tp->bufmgr_config.mbuf_read_dma_low_water =
                        DEFAULT_MB_RDMA_LOW_WATER_5705;
@@ -14179,6 +14209,7 @@ static char * __devinit tg3_phy_string(struct tg3 *tp)
        case TG3_PHY_ID_BCM5718C:       return "5718C";
        case TG3_PHY_ID_BCM5718S:       return "5718S";
        case TG3_PHY_ID_BCM57765:       return "57765";
+       case TG3_PHY_ID_BCM5719C:       return "5719C";
        case TG3_PHY_ID_BCM8002:        return "8002/serdes";
        case 0:                 return "serdes";
        default:                return "unknown";
@@ -14284,7 +14315,7 @@ static const struct net_device_ops tg3_netdev_ops = {
        .ndo_open               = tg3_open,
        .ndo_stop               = tg3_close,
        .ndo_start_xmit         = tg3_start_xmit,
-       .ndo_get_stats          = tg3_get_stats,
+       .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,
@@ -14303,7 +14334,7 @@ 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_stats          = tg3_get_stats,
+       .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,
@@ -14427,7 +14458,8 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
        }
 
        if ((tp->tg3_flags3 & TG3_FLG3_5755_PLUS) &&
-           tp->pci_chip_rev_id != CHIPREV_ID_5717_A0)
+           tp->pci_chip_rev_id != CHIPREV_ID_5717_A0 &&
+           GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5719)
                dev->netdev_ops = &tg3_netdev_ops;
        else
                dev->netdev_ops = &tg3_netdev_ops_dma_bug;
@@ -14491,20 +14523,25 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
         * is off by default, but can be enabled using ethtool.
         */
        if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO) &&
-           (dev->features & NETIF_F_IP_CSUM))
+           (dev->features & NETIF_F_IP_CSUM)) {
                dev->features |= NETIF_F_TSO;
-
+               vlan_features_add(dev, NETIF_F_TSO);
+       }
        if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO_2) ||
            (tp->tg3_flags2 & TG3_FLG2_HW_TSO_3)) {
-               if (dev->features & NETIF_F_IPV6_CSUM)
+               if (dev->features & NETIF_F_IPV6_CSUM) {
                        dev->features |= NETIF_F_TSO6;
+                       vlan_features_add(dev, NETIF_F_TSO6);
+               }
                if ((tp->tg3_flags2 & TG3_FLG2_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)
+                   GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780) {
                        dev->features |= NETIF_F_TSO_ECN;
+                       vlan_features_add(dev, NETIF_F_TSO_ECN);
+               }
        }
 
        if (tp->pci_chip_rev_id == CHIPREV_ID_5705_A1 &&