]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - drivers/net/tg3.c
tg3: Report invalid link from tg3_get_settings()
[net-next-2.6.git] / drivers / net / tg3.c
index e7a2ba8b20a22833a184b4ac903e2381c6d7772a..5d30e67ffe69fe2c6676ee9c4ca9665228f6b1fc 100644 (file)
 
 #define DRV_MODULE_NAME                "tg3"
 #define TG3_MAJ_NUM                    3
-#define TG3_MIN_NUM                    113
+#define TG3_MIN_NUM                    114
 #define DRV_MODULE_VERSION     \
        __stringify(TG3_MAJ_NUM) "." __stringify(TG3_MIN_NUM)
-#define DRV_MODULE_RELDATE     "August 2, 2010"
+#define DRV_MODULE_RELDATE     "September 30, 2010"
 
 #define TG3_DEF_MAC_MODE       0
 #define TG3_DEF_RX_MODE                0
  * You can't change the ring sizes, but you can change where you place
  * them in the NIC onboard memory.
  */
-#define TG3_RX_RING_SIZE               512
+#define TG3_RX_STD_RING_SIZE(tp) \
+       ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || \
+         GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) ? \
+        RX_STD_MAX_SIZE_5717 : 512)
 #define TG3_DEF_RX_RING_PENDING                200
-#define TG3_RX_JUMBO_RING_SIZE         256
+#define TG3_RX_JMB_RING_SIZE(tp) \
+       ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || \
+         GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) ? \
+        1024 : 256)
 #define TG3_DEF_RX_JUMBO_RING_PENDING  100
 #define TG3_RSS_INDIR_TBL_SIZE         128
 
  * hw multiply/modulo instructions.  Another solution would be to
  * replace things like '% foo' with '& (foo - 1)'.
  */
-#define TG3_RX_RCB_RING_SIZE(tp)       \
-       (((tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) && \
-         !(tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) ? 1024 : 512)
 
 #define TG3_TX_RING_SIZE               512
 #define TG3_DEF_TX_RING_PENDING                (TG3_TX_RING_SIZE - 1)
 
-#define TG3_RX_RING_BYTES      (sizeof(struct tg3_rx_buffer_desc) * \
-                                TG3_RX_RING_SIZE)
-#define TG3_RX_JUMBO_RING_BYTES        (sizeof(struct tg3_ext_rx_buffer_desc) * \
-                                TG3_RX_JUMBO_RING_SIZE)
-#define TG3_RX_RCB_RING_BYTES(tp) (sizeof(struct tg3_rx_buffer_desc) * \
-                                TG3_RX_RCB_RING_SIZE(tp))
+#define TG3_RX_STD_RING_BYTES(tp) \
+       (sizeof(struct tg3_rx_buffer_desc) * TG3_RX_STD_RING_SIZE(tp))
+#define TG3_RX_JMB_RING_BYTES(tp) \
+       (sizeof(struct tg3_ext_rx_buffer_desc) * TG3_RX_JMB_RING_SIZE(tp))
+#define TG3_RX_RCB_RING_BYTES(tp) \
+       (sizeof(struct tg3_rx_buffer_desc) * (tp->rx_ret_ring_mask + 1))
 #define TG3_TX_RING_BYTES      (sizeof(struct tg3_tx_buffer_desc) * \
                                 TG3_TX_RING_SIZE)
 #define NEXT_TX(N)             (((N) + 1) & (TG3_TX_RING_SIZE - 1))
 #define TG3_RX_STD_MAP_SZ              TG3_RX_DMA_TO_MAP_SZ(TG3_RX_STD_DMA_SZ)
 #define TG3_RX_JMB_MAP_SZ              TG3_RX_DMA_TO_MAP_SZ(TG3_RX_JMB_DMA_SZ)
 
-#define TG3_RX_STD_BUFF_RING_SIZE \
-       (sizeof(struct ring_info) * TG3_RX_RING_SIZE)
+#define TG3_RX_STD_BUFF_RING_SIZE(tp) \
+       (sizeof(struct ring_info) * TG3_RX_STD_RING_SIZE(tp))
 
-#define TG3_RX_JMB_BUFF_RING_SIZE \
-       (sizeof(struct ring_info) * TG3_RX_JUMBO_RING_SIZE)
+#define TG3_RX_JMB_BUFF_RING_SIZE(tp) \
+       (sizeof(struct ring_info) * TG3_RX_JMB_RING_SIZE(tp))
 
 /* 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
@@ -264,7 +267,6 @@ static DEFINE_PCI_DEVICE_TABLE(tg3_pci_tbl) = {
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57788)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5717)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5718)},
-       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5724)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57781)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57785)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57761)},
@@ -752,42 +754,6 @@ static void tg3_int_reenable(struct tg3_napi *tnapi)
                     HOSTCC_MODE_ENABLE | tnapi->coal_now);
 }
 
-static void tg3_napi_disable(struct tg3 *tp)
-{
-       int i;
-
-       for (i = tp->irq_cnt - 1; i >= 0; i--)
-               napi_disable(&tp->napi[i].napi);
-}
-
-static void tg3_napi_enable(struct tg3 *tp)
-{
-       int i;
-
-       for (i = 0; i < tp->irq_cnt; i++)
-               napi_enable(&tp->napi[i].napi);
-}
-
-static inline void tg3_netif_stop(struct tg3 *tp)
-{
-       tp->dev->trans_start = jiffies; /* prevent tx timeout */
-       tg3_napi_disable(tp);
-       netif_tx_disable(tp->dev);
-}
-
-static inline void tg3_netif_start(struct tg3 *tp)
-{
-       /* NOTE: unconditional netif_tx_wake_all_queues is only
-        * appropriate so long as all callers are assured to
-        * have free tx slots (such as after tg3_init_hw)
-        */
-       netif_tx_wake_all_queues(tp->dev);
-
-       tg3_napi_enable(tp);
-       tp->napi[0].hw_status->status |= SD_STATUS_UPDATED;
-       tg3_enable_ints(tp);
-}
-
 static void tg3_switch_clocks(struct tg3 *tp)
 {
        u32 clock_ctrl;
@@ -1196,6 +1162,52 @@ static void tg3_mdio_fini(struct tg3 *tp)
        }
 }
 
+static int tg3_phy_cl45_write(struct tg3 *tp, u32 devad, u32 addr, u32 val)
+{
+       int err;
+
+       err = tg3_writephy(tp, MII_TG3_MMD_CTRL, devad);
+       if (err)
+               goto done;
+
+       err = tg3_writephy(tp, MII_TG3_MMD_ADDRESS, addr);
+       if (err)
+               goto done;
+
+       err = tg3_writephy(tp, MII_TG3_MMD_CTRL,
+                          MII_TG3_MMD_CTRL_DATA_NOINC | devad);
+       if (err)
+               goto done;
+
+       err = tg3_writephy(tp, MII_TG3_MMD_ADDRESS, val);
+
+done:
+       return err;
+}
+
+static int tg3_phy_cl45_read(struct tg3 *tp, u32 devad, u32 addr, u32 *val)
+{
+       int err;
+
+       err = tg3_writephy(tp, MII_TG3_MMD_CTRL, devad);
+       if (err)
+               goto done;
+
+       err = tg3_writephy(tp, MII_TG3_MMD_ADDRESS, addr);
+       if (err)
+               goto done;
+
+       err = tg3_writephy(tp, MII_TG3_MMD_CTRL,
+                          MII_TG3_MMD_CTRL_DATA_NOINC | devad);
+       if (err)
+               goto done;
+
+       err = tg3_readphy(tp, MII_TG3_MMD_ADDRESS, val);
+
+done:
+       return err;
+}
+
 /* tp->lock is held. */
 static inline void tg3_generate_fw_event(struct tg3 *tp)
 {
@@ -1572,6 +1584,17 @@ static void tg3_phy_fini(struct tg3 *tp)
        }
 }
 
+static int tg3_phydsp_read(struct tg3 *tp, u32 reg, u32 *val)
+{
+       int err;
+
+       err = tg3_writephy(tp, MII_TG3_DSP_ADDRESS, reg);
+       if (!err)
+               err = tg3_readphy(tp, MII_TG3_DSP_RW_PORT, val);
+
+       return err;
+}
+
 static int tg3_phydsp_write(struct tg3 *tp, u32 reg, u32 val)
 {
        int err;
@@ -1735,6 +1758,42 @@ static void tg3_phy_apply_otp(struct tg3 *tp)
        tg3_writephy(tp, MII_TG3_AUX_CTRL, phy);
 }
 
+static void tg3_phy_eee_adjust(struct tg3 *tp, u32 current_link_up)
+{
+       u32 val;
+
+       if (!(tp->phy_flags & TG3_PHYFLG_EEE_CAP))
+               return;
+
+       tp->setlpicnt = 0;
+
+       if (tp->link_config.autoneg == AUTONEG_ENABLE &&
+           current_link_up == 1 &&
+           (tp->link_config.active_speed == SPEED_1000 ||
+            (tp->link_config.active_speed == SPEED_100 &&
+             tp->link_config.active_duplex == DUPLEX_FULL))) {
+               u32 eeectl;
+
+               if (tp->link_config.active_speed == SPEED_1000)
+                       eeectl = TG3_CPMU_EEE_CTRL_EXIT_16_5_US;
+               else
+                       eeectl = TG3_CPMU_EEE_CTRL_EXIT_36_US;
+
+               tw32(TG3_CPMU_EEE_CTRL, eeectl);
+
+               tg3_phy_cl45_read(tp, 0x7, TG3_CL45_D7_EEERES_STAT, &val);
+
+               if (val == TG3_CL45_D7_EEERES_STAT_LP_1000T ||
+                   val == TG3_CL45_D7_EEERES_STAT_LP_100TX)
+                       tp->setlpicnt = 2;
+       }
+
+       if (!tp->setlpicnt) {
+               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;
@@ -2909,6 +2968,44 @@ static void tg3_phy_copper_begin(struct tg3 *tp)
                tg3_writephy(tp, MII_TG3_CTRL, new_adv);
        }
 
+       if (tp->phy_flags & TG3_PHYFLG_EEE_CAP) {
+               u32 val = 0;
+
+               tw32(TG3_CPMU_EEE_MODE,
+                    tr32(TG3_CPMU_EEE_MODE) & ~TG3_CPMU_EEEMD_LPI_ENABLE);
+
+               /* Enable SM_DSP clock and tx 6dB coding. */
+               val = MII_TG3_AUXCTL_SHDWSEL_AUXCTL |
+                     MII_TG3_AUXCTL_ACTL_SMDSP_ENA |
+                     MII_TG3_AUXCTL_ACTL_TX_6DB;
+               tg3_writephy(tp, MII_TG3_AUX_CTRL, val);
+
+               if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
+                    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) &&
+                   !tg3_phydsp_read(tp, MII_TG3_DSP_CH34TP2, &val))
+                       tg3_phydsp_write(tp, MII_TG3_DSP_CH34TP2,
+                                        val | MII_TG3_DSP_CH34TP2_HIBW01);
+
+               if (tp->link_config.autoneg == AUTONEG_ENABLE) {
+                       /* Advertise 100-BaseTX EEE ability */
+                       if (tp->link_config.advertising &
+                           (ADVERTISED_100baseT_Half |
+                            ADVERTISED_100baseT_Full))
+                               val |= TG3_CL45_D7_EEEADV_CAP_100TX;
+                       /* Advertise 1000-BaseT EEE ability */
+                       if (tp->link_config.advertising &
+                           (ADVERTISED_1000baseT_Half |
+                            ADVERTISED_1000baseT_Full))
+                               val |= TG3_CL45_D7_EEEADV_CAP_1000T;
+               }
+               tg3_phy_cl45_write(tp, 0x7, TG3_CL45_D7_EEEADV_CAP, val);
+
+               /* Turn off SM_DSP clock. */
+               val = MII_TG3_AUXCTL_SHDWSEL_AUXCTL |
+                     MII_TG3_AUXCTL_ACTL_TX_6DB;
+               tg3_writephy(tp, MII_TG3_AUX_CTRL, val);
+       }
+
        if (tp->link_config.autoneg == AUTONEG_DISABLE &&
            tp->link_config.speed != SPEED_INVALID) {
                u32 bmcr, orig_bmcr;
@@ -3270,6 +3367,8 @@ relink:
        tw32_f(MAC_MODE, tp->mac_mode);
        udelay(40);
 
+       tg3_phy_eee_adjust(tp, current_link_up);
+
        if (tp->tg3_flags & TG3_FLAG_USE_LINKCHG_REG) {
                /* Polled via timer. */
                tw32_f(MAC_EVENT, 0);
@@ -4338,6 +4437,11 @@ static int tg3_setup_phy(struct tg3 *tp, int force_reset)
        return err;
 }
 
+static inline int tg3_irq_sync(struct tg3 *tp)
+{
+       return tp->irq_sync;
+}
+
 /* This is called whenever we suspect that the system chipset is re-
  * ordering the sequence of MMIO to the tx send mailbox. The symptom
  * is bogus tx completions. We try to recover by setting the
@@ -4469,22 +4573,21 @@ static int tg3_alloc_rx_skb(struct tg3 *tp, struct tg3_rx_prodring_set *tpr,
                            u32 opaque_key, u32 dest_idx_unmasked)
 {
        struct tg3_rx_buffer_desc *desc;
-       struct ring_info *map, *src_map;
+       struct ring_info *map;
        struct sk_buff *skb;
        dma_addr_t mapping;
        int skb_size, dest_idx;
 
-       src_map = NULL;
        switch (opaque_key) {
        case RXD_OPAQUE_RING_STD:
-               dest_idx = dest_idx_unmasked % TG3_RX_RING_SIZE;
+               dest_idx = dest_idx_unmasked & tp->rx_std_ring_mask;
                desc = &tpr->rx_std[dest_idx];
                map = &tpr->rx_std_buffers[dest_idx];
                skb_size = tp->rx_pkt_map_sz;
                break;
 
        case RXD_OPAQUE_RING_JUMBO:
-               dest_idx = dest_idx_unmasked % TG3_RX_JUMBO_RING_SIZE;
+               dest_idx = dest_idx_unmasked & tp->rx_jmb_ring_mask;
                desc = &tpr->rx_jmb[dest_idx].std;
                map = &tpr->rx_jmb_buffers[dest_idx];
                skb_size = TG3_RX_JMB_MAP_SZ;
@@ -4539,7 +4642,7 @@ static void tg3_recycle_rx(struct tg3_napi *tnapi,
 
        switch (opaque_key) {
        case RXD_OPAQUE_RING_STD:
-               dest_idx = dest_idx_unmasked % TG3_RX_RING_SIZE;
+               dest_idx = dest_idx_unmasked & tp->rx_std_ring_mask;
                dest_desc = &dpr->rx_std[dest_idx];
                dest_map = &dpr->rx_std_buffers[dest_idx];
                src_desc = &spr->rx_std[src_idx];
@@ -4547,7 +4650,7 @@ static void tg3_recycle_rx(struct tg3_napi *tnapi,
                break;
 
        case RXD_OPAQUE_RING_JUMBO:
-               dest_idx = dest_idx_unmasked % TG3_RX_JUMBO_RING_SIZE;
+               dest_idx = dest_idx_unmasked & tp->rx_jmb_ring_mask;
                dest_desc = &dpr->rx_jmb[dest_idx].std;
                dest_map = &dpr->rx_jmb_buffers[dest_idx];
                src_desc = &spr->rx_jmb[src_idx].std;
@@ -4747,7 +4850,8 @@ next_pkt:
                (*post_ptr)++;
 
                if (unlikely(rx_std_posted >= tp->rx_std_max_post)) {
-                       tpr->rx_std_prod_idx = std_prod_idx % TG3_RX_RING_SIZE;
+                       tpr->rx_std_prod_idx = std_prod_idx &
+                                              tp->rx_std_ring_mask;
                        tw32_rx_mbox(TG3_RX_STD_PROD_IDX_REG,
                                     tpr->rx_std_prod_idx);
                        work_mask &= ~RXD_OPAQUE_RING_STD;
@@ -4755,7 +4859,7 @@ next_pkt:
                }
 next_pkt_nopost:
                sw_idx++;
-               sw_idx &= (TG3_RX_RCB_RING_SIZE(tp) - 1);
+               sw_idx &= tp->rx_ret_ring_mask;
 
                /* Refresh hw_idx to see if there is new work */
                if (sw_idx == hw_idx) {
@@ -4771,13 +4875,14 @@ next_pkt_nopost:
        /* Refill RX ring(s). */
        if (!(tp->tg3_flags3 & TG3_FLG3_ENABLE_RSS)) {
                if (work_mask & RXD_OPAQUE_RING_STD) {
-                       tpr->rx_std_prod_idx = std_prod_idx % TG3_RX_RING_SIZE;
+                       tpr->rx_std_prod_idx = std_prod_idx &
+                                              tp->rx_std_ring_mask;
                        tw32_rx_mbox(TG3_RX_STD_PROD_IDX_REG,
                                     tpr->rx_std_prod_idx);
                }
                if (work_mask & RXD_OPAQUE_RING_JUMBO) {
-                       tpr->rx_jmb_prod_idx = jmb_prod_idx %
-                                              TG3_RX_JUMBO_RING_SIZE;
+                       tpr->rx_jmb_prod_idx = jmb_prod_idx &
+                                              tp->rx_jmb_ring_mask;
                        tw32_rx_mbox(TG3_RX_JMB_PROD_IDX_REG,
                                     tpr->rx_jmb_prod_idx);
                }
@@ -4788,8 +4893,8 @@ next_pkt_nopost:
                 */
                smp_wmb();
 
-               tpr->rx_std_prod_idx = std_prod_idx % TG3_RX_RING_SIZE;
-               tpr->rx_jmb_prod_idx = jmb_prod_idx % TG3_RX_JUMBO_RING_SIZE;
+               tpr->rx_std_prod_idx = std_prod_idx & tp->rx_std_ring_mask;
+               tpr->rx_jmb_prod_idx = jmb_prod_idx & tp->rx_jmb_ring_mask;
 
                if (tnapi != &tp->napi[1])
                        napi_schedule(&tp->napi[1].napi);
@@ -4845,9 +4950,11 @@ static int tg3_rx_prodring_xfer(struct tg3 *tp,
                if (spr->rx_std_cons_idx < src_prod_idx)
                        cpycnt = src_prod_idx - spr->rx_std_cons_idx;
                else
-                       cpycnt = TG3_RX_RING_SIZE - spr->rx_std_cons_idx;
+                       cpycnt = tp->rx_std_ring_mask + 1 -
+                                spr->rx_std_cons_idx;
 
-               cpycnt = min(cpycnt, TG3_RX_RING_SIZE - dpr->rx_std_prod_idx);
+               cpycnt = min(cpycnt,
+                            tp->rx_std_ring_mask + 1 - dpr->rx_std_prod_idx);
 
                si = spr->rx_std_cons_idx;
                di = dpr->rx_std_prod_idx;
@@ -4881,10 +4988,10 @@ static int tg3_rx_prodring_xfer(struct tg3 *tp,
                        dbd->addr_lo = sbd->addr_lo;
                }
 
-               spr->rx_std_cons_idx = (spr->rx_std_cons_idx + cpycnt) %
-                                      TG3_RX_RING_SIZE;
-               dpr->rx_std_prod_idx = (dpr->rx_std_prod_idx + cpycnt) %
-                                      TG3_RX_RING_SIZE;
+               spr->rx_std_cons_idx = (spr->rx_std_cons_idx + cpycnt) &
+                                      tp->rx_std_ring_mask;
+               dpr->rx_std_prod_idx = (dpr->rx_std_prod_idx + cpycnt) &
+                                      tp->rx_std_ring_mask;
        }
 
        while (1) {
@@ -4901,10 +5008,11 @@ static int tg3_rx_prodring_xfer(struct tg3 *tp,
                if (spr->rx_jmb_cons_idx < src_prod_idx)
                        cpycnt = src_prod_idx - spr->rx_jmb_cons_idx;
                else
-                       cpycnt = TG3_RX_JUMBO_RING_SIZE - spr->rx_jmb_cons_idx;
+                       cpycnt = tp->rx_jmb_ring_mask + 1 -
+                                spr->rx_jmb_cons_idx;
 
                cpycnt = min(cpycnt,
-                            TG3_RX_JUMBO_RING_SIZE - dpr->rx_jmb_prod_idx);
+                            tp->rx_jmb_ring_mask + 1 - dpr->rx_jmb_prod_idx);
 
                si = spr->rx_jmb_cons_idx;
                di = dpr->rx_jmb_prod_idx;
@@ -4938,10 +5046,10 @@ static int tg3_rx_prodring_xfer(struct tg3 *tp,
                        dbd->addr_lo = sbd->addr_lo;
                }
 
-               spr->rx_jmb_cons_idx = (spr->rx_jmb_cons_idx + cpycnt) %
-                                      TG3_RX_JUMBO_RING_SIZE;
-               dpr->rx_jmb_prod_idx = (dpr->rx_jmb_prod_idx + cpycnt) %
-                                      TG3_RX_JUMBO_RING_SIZE;
+               spr->rx_jmb_cons_idx = (spr->rx_jmb_cons_idx + cpycnt) &
+                                      tp->rx_jmb_ring_mask;
+               dpr->rx_jmb_prod_idx = (dpr->rx_jmb_prod_idx + cpycnt) &
+                                      tp->rx_jmb_ring_mask;
        }
 
        return err;
@@ -5083,6 +5191,59 @@ tx_recovery:
        return work_done;
 }
 
+static void tg3_napi_disable(struct tg3 *tp)
+{
+       int i;
+
+       for (i = tp->irq_cnt - 1; i >= 0; i--)
+               napi_disable(&tp->napi[i].napi);
+}
+
+static void tg3_napi_enable(struct tg3 *tp)
+{
+       int i;
+
+       for (i = 0; i < tp->irq_cnt; i++)
+               napi_enable(&tp->napi[i].napi);
+}
+
+static void tg3_napi_init(struct tg3 *tp)
+{
+       int i;
+
+       netif_napi_add(tp->dev, &tp->napi[0].napi, tg3_poll, 64);
+       for (i = 1; i < tp->irq_cnt; i++)
+               netif_napi_add(tp->dev, &tp->napi[i].napi, tg3_poll_msix, 64);
+}
+
+static void tg3_napi_fini(struct tg3 *tp)
+{
+       int i;
+
+       for (i = 0; i < tp->irq_cnt; i++)
+               netif_napi_del(&tp->napi[i].napi);
+}
+
+static inline void tg3_netif_stop(struct tg3 *tp)
+{
+       tp->dev->trans_start = jiffies; /* prevent tx timeout */
+       tg3_napi_disable(tp);
+       netif_tx_disable(tp->dev);
+}
+
+static inline void tg3_netif_start(struct tg3 *tp)
+{
+       /* NOTE: unconditional netif_tx_wake_all_queues is only
+        * appropriate so long as all callers are assured to
+        * have free tx slots (such as after tg3_init_hw)
+        */
+       netif_tx_wake_all_queues(tp->dev);
+
+       tg3_napi_enable(tp);
+       tp->napi[0].hw_status->status |= SD_STATUS_UPDATED;
+       tg3_enable_ints(tp);
+}
+
 static void tg3_irq_quiesce(struct tg3 *tp)
 {
        int i;
@@ -5096,11 +5257,6 @@ static void tg3_irq_quiesce(struct tg3 *tp)
                synchronize_irq(tp->napi[i].irq_vec);
 }
 
-static inline int tg3_irq_sync(struct tg3 *tp)
-{
-       return tp->irq_sync;
-}
-
 /* Fully shutdown all tg3 driver activity elsewhere in the system.
  * If irq_sync is non-zero, then the IRQ handler must be synchronized
  * with as well.  Most of the time, this is not necessary except when
@@ -5389,8 +5545,7 @@ static inline int tg3_4g_overflow_test(dma_addr_t mapping, int len)
 {
        u32 base = (u32) mapping & 0xffffffff;
 
-       return ((base > 0xffffdcc0) &&
-               (base + len + 8 < base));
+       return (base > 0xffffdcc0) && (base + len + 8 < base);
 }
 
 /* Test for DMA addresses > 40-bit */
@@ -5399,7 +5554,7 @@ static inline int tg3_40bit_overflow_test(struct tg3 *tp, dma_addr_t mapping,
 {
 #if defined(CONFIG_HIGHMEM) && (BITS_PER_LONG == 64)
        if (tp->tg3_flags & TG3_FLAG_40BIT_DMA_BUG)
-               return (((u64) mapping + len) > DMA_BIT_MASK(40));
+               return ((u64) mapping + len) > DMA_BIT_MASK(40);
        return 0;
 #else
        return 0;
@@ -6044,14 +6199,14 @@ static void tg3_rx_prodring_free(struct tg3 *tp,
 
        if (tpr != &tp->napi[0].prodring) {
                for (i = tpr->rx_std_cons_idx; i != tpr->rx_std_prod_idx;
-                    i = (i + 1) % TG3_RX_RING_SIZE)
+                    i = (i + 1) & tp->rx_std_ring_mask)
                        tg3_rx_skb_free(tp, &tpr->rx_std_buffers[i],
                                        tp->rx_pkt_map_sz);
 
                if (tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) {
                        for (i = tpr->rx_jmb_cons_idx;
                             i != tpr->rx_jmb_prod_idx;
-                            i = (i + 1) % TG3_RX_JUMBO_RING_SIZE) {
+                            i = (i + 1) & tp->rx_jmb_ring_mask) {
                                tg3_rx_skb_free(tp, &tpr->rx_jmb_buffers[i],
                                                TG3_RX_JMB_MAP_SZ);
                        }
@@ -6060,12 +6215,13 @@ static void tg3_rx_prodring_free(struct tg3 *tp,
                return;
        }
 
-       for (i = 0; i < TG3_RX_RING_SIZE; i++)
+       for (i = 0; i <= tp->rx_std_ring_mask; i++)
                tg3_rx_skb_free(tp, &tpr->rx_std_buffers[i],
                                tp->rx_pkt_map_sz);
 
-       if (tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) {
-               for (i = 0; i < TG3_RX_JUMBO_RING_SIZE; i++)
+       if ((tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) &&
+           !(tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) {
+               for (i = 0; i <= tp->rx_jmb_ring_mask; i++)
                        tg3_rx_skb_free(tp, &tpr->rx_jmb_buffers[i],
                                        TG3_RX_JMB_MAP_SZ);
        }
@@ -6089,15 +6245,16 @@ static int tg3_rx_prodring_alloc(struct tg3 *tp,
        tpr->rx_jmb_prod_idx = 0;
 
        if (tpr != &tp->napi[0].prodring) {
-               memset(&tpr->rx_std_buffers[0], 0, TG3_RX_STD_BUFF_RING_SIZE);
-               if (tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE)
+               memset(&tpr->rx_std_buffers[0], 0,
+                      TG3_RX_STD_BUFF_RING_SIZE(tp));
+               if (tpr->rx_jmb_buffers)
                        memset(&tpr->rx_jmb_buffers[0], 0,
-                              TG3_RX_JMB_BUFF_RING_SIZE);
+                              TG3_RX_JMB_BUFF_RING_SIZE(tp));
                goto done;
        }
 
        /* Zero out all descriptors. */
-       memset(tpr->rx_std, 0, TG3_RX_RING_BYTES);
+       memset(tpr->rx_std, 0, TG3_RX_STD_RING_BYTES(tp));
 
        rx_pkt_dma_sz = TG3_RX_STD_DMA_SZ;
        if ((tp->tg3_flags2 & TG3_FLG2_5780_CLASS) &&
@@ -6109,7 +6266,7 @@ static int tg3_rx_prodring_alloc(struct tg3 *tp,
         * stuff once.  This works because the card does not
         * write into the rx buffer posting rings.
         */
-       for (i = 0; i < TG3_RX_RING_SIZE; i++) {
+       for (i = 0; i <= tp->rx_std_ring_mask; i++) {
                struct tg3_rx_buffer_desc *rxd;
 
                rxd = &tpr->rx_std[i];
@@ -6133,15 +6290,16 @@ static int tg3_rx_prodring_alloc(struct tg3 *tp,
                }
        }
 
-       if (!(tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE))
+       if (!(tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) ||
+           (tp->tg3_flags2 & TG3_FLG2_5780_CLASS))
                goto done;
 
-       memset(tpr->rx_jmb, 0, TG3_RX_JUMBO_RING_BYTES);
+       memset(tpr->rx_jmb, 0, TG3_RX_JMB_RING_BYTES(tp));
 
        if (!(tp->tg3_flags & TG3_FLAG_JUMBO_RING_ENABLE))
                goto done;
 
-       for (i = 0; i < TG3_RX_JUMBO_RING_SIZE; i++) {
+       for (i = 0; i <= tp->rx_jmb_ring_mask; i++) {
                struct tg3_rx_buffer_desc *rxd;
 
                rxd = &tpr->rx_jmb[i].std;
@@ -6181,12 +6339,12 @@ static void tg3_rx_prodring_fini(struct tg3 *tp,
        kfree(tpr->rx_jmb_buffers);
        tpr->rx_jmb_buffers = NULL;
        if (tpr->rx_std) {
-               pci_free_consistent(tp->pdev, TG3_RX_RING_BYTES,
+               pci_free_consistent(tp->pdev, TG3_RX_STD_RING_BYTES(tp),
                                    tpr->rx_std, tpr->rx_std_mapping);
                tpr->rx_std = NULL;
        }
        if (tpr->rx_jmb) {
-               pci_free_consistent(tp->pdev, TG3_RX_JUMBO_RING_BYTES,
+               pci_free_consistent(tp->pdev, TG3_RX_JMB_RING_BYTES(tp),
                                    tpr->rx_jmb, tpr->rx_jmb_mapping);
                tpr->rx_jmb = NULL;
        }
@@ -6195,23 +6353,25 @@ static void tg3_rx_prodring_fini(struct tg3 *tp,
 static int tg3_rx_prodring_init(struct tg3 *tp,
                                struct tg3_rx_prodring_set *tpr)
 {
-       tpr->rx_std_buffers = kzalloc(TG3_RX_STD_BUFF_RING_SIZE, GFP_KERNEL);
+       tpr->rx_std_buffers = kzalloc(TG3_RX_STD_BUFF_RING_SIZE(tp),
+                                     GFP_KERNEL);
        if (!tpr->rx_std_buffers)
                return -ENOMEM;
 
-       tpr->rx_std = pci_alloc_consistent(tp->pdev, TG3_RX_RING_BYTES,
+       tpr->rx_std = pci_alloc_consistent(tp->pdev, TG3_RX_STD_RING_BYTES(tp),
                                           &tpr->rx_std_mapping);
        if (!tpr->rx_std)
                goto err_out;
 
-       if (tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) {
-               tpr->rx_jmb_buffers = kzalloc(TG3_RX_JMB_BUFF_RING_SIZE,
+       if ((tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) &&
+           !(tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) {
+               tpr->rx_jmb_buffers = kzalloc(TG3_RX_JMB_BUFF_RING_SIZE(tp),
                                              GFP_KERNEL);
                if (!tpr->rx_jmb_buffers)
                        goto err_out;
 
                tpr->rx_jmb = pci_alloc_consistent(tp->pdev,
-                                                  TG3_RX_JUMBO_RING_BYTES,
+                                                  TG3_RX_JMB_RING_BYTES(tp),
                                                   &tpr->rx_jmb_mapping);
                if (!tpr->rx_jmb)
                        goto err_out;
@@ -7511,6 +7671,9 @@ static void tg3_rings_reset(struct tg3 *tp)
        /* Disable all transmit rings but the first. */
        if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS))
                limit = NIC_SRAM_SEND_RCB + TG3_BDINFO_SIZE * 16;
+       else 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_SEND_RCB + TG3_BDINFO_SIZE * 4;
        else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765)
                limit = NIC_SRAM_SEND_RCB + TG3_BDINFO_SIZE * 2;
        else
@@ -7590,8 +7753,8 @@ static void tg3_rings_reset(struct tg3 *tp)
 
        if (tnapi->rx_rcb) {
                tg3_set_bdinfo(tp, rxrcb, tnapi->rx_rcb_mapping,
-                              (TG3_RX_RCB_RING_SIZE(tp) <<
-                               BDINFO_FLAGS_MAXLEN_SHIFT), 0);
+                              (tp->rx_ret_ring_mask + 1) <<
+                               BDINFO_FLAGS_MAXLEN_SHIFT, 0);
                rxrcb += TG3_BDINFO_SIZE;
        }
 
@@ -7614,7 +7777,7 @@ static void tg3_rings_reset(struct tg3 *tp)
                }
 
                tg3_set_bdinfo(tp, rxrcb, tnapi->rx_rcb_mapping,
-                              (TG3_RX_RCB_RING_SIZE(tp) <<
+                              ((tp->rx_ret_ring_mask + 1) <<
                                BDINFO_FLAGS_MAXLEN_SHIFT), 0);
 
                stblk += 8;
@@ -7716,6 +7879,22 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
                tw32(TG3_CPMU_LSPD_10MB_CLK, val);
        }
 
+       /* Enable MAC control of LPI */
+       if (tp->phy_flags & TG3_PHYFLG_EEE_CAP) {
+               tw32_f(TG3_CPMU_EEE_LNKIDL_CTRL,
+                      TG3_CPMU_EEE_LNKIDL_PCIE_NL0 |
+                      TG3_CPMU_EEE_LNKIDL_UART_IDL);
+
+               tw32_f(TG3_CPMU_EEE_CTRL,
+                      TG3_CPMU_EEE_CTRL_EXIT_20_1_US);
+
+               tw32_f(TG3_CPMU_EEE_MODE,
+                      TG3_CPMU_EEEMD_ERLY_L1_XIT_DET |
+                      TG3_CPMU_EEEMD_LPI_IN_TX |
+                      TG3_CPMU_EEEMD_LPI_IN_RX |
+                      TG3_CPMU_EEEMD_EEE_ENABLE);
+       }
+
        /* This works around an issue with Athlon chipsets on
         * B3 tigon3 silicon.  This bit has no effect on any
         * other revision.  But do not set this on PCI Express
@@ -7841,7 +8020,10 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
        tw32(BUFMGR_DMA_HIGH_WATER,
             tp->bufmgr_config.dma_high_water);
 
-       tw32(BUFMGR_MODE, BUFMGR_MODE_ENABLE | BUFMGR_MODE_ATTN_ENABLE);
+       val = BUFMGR_MODE_ENABLE | BUFMGR_MODE_ATTN_ENABLE;
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719)
+               val |= BUFMGR_MODE_NO_TX_UNDERRUN;
+       tw32(BUFMGR_MODE, val);
        for (i = 0; i < 2000; i++) {
                if (tr32(BUFMGR_MODE) & BUFMGR_MODE_ENABLE)
                        break;
@@ -7924,10 +8106,14 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
                             BDINFO_FLAGS_DISABLED);
                }
 
-               if (tp->tg3_flags3 & TG3_FLG3_5717_PLUS)
-                       val = (RX_STD_MAX_SIZE_5705 << BDINFO_FLAGS_MAXLEN_SHIFT) |
-                             (TG3_RX_STD_DMA_SZ << 2);
-               else
+               if (tp->tg3_flags3 & TG3_FLG3_5717_PLUS) {
+                       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765)
+                               val = RX_STD_MAX_SIZE_5705;
+                       else
+                               val = RX_STD_MAX_SIZE_5717;
+                       val <<= BDINFO_FLAGS_MAXLEN_SHIFT;
+                       val |= (TG3_RX_STD_DMA_SZ << 2);
+               } else
                        val = TG3_RX_STD_DMA_SZ << BDINFO_FLAGS_MAXLEN_SHIFT;
        } else
                val = RX_STD_MAX_SIZE_5705 << BDINFO_FLAGS_MAXLEN_SHIFT;
@@ -8021,6 +8207,13 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
                     val | TG3_RDMA_RSRVCTRL_FIFO_OFLW_FIX);
        }
 
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) {
+               val = tr32(TG3_LSO_RD_DMA_CRPTEN_CTRL);
+               tw32(TG3_LSO_RD_DMA_CRPTEN_CTRL, val |
+                    TG3_LSO_RD_DMA_CRPTEN_CTRL_BLEN_BD_4K |
+                    TG3_LSO_RD_DMA_CRPTEN_CTRL_BLEN_LSO_4K);
+       }
+
        /* Receive/send statistics. */
        if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) {
                val = tr32(RCVLPC_STATS_ENABLE);
@@ -8203,7 +8396,11 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
 
        tw32(SNDBDC_MODE, SNDBDC_MODE_ENABLE | SNDBDC_MODE_ATTN_ENABLE);
        tw32(RCVBDI_MODE, RCVBDI_MODE_ENABLE | RCVBDI_MODE_RCB_ATTN_ENAB);
-       tw32(RCVDBDI_MODE, RCVDBDI_MODE_ENABLE | RCVDBDI_MODE_INV_RING_SZ);
+       val = RCVDBDI_MODE_ENABLE | RCVDBDI_MODE_INV_RING_SZ;
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719)
+               val |= RCVDBDI_MODE_LRG_RING_SZ;
+       tw32(RCVDBDI_MODE, val);
        tw32(SNDDATAI_MODE, SNDDATAI_MODE_ENABLE);
        if (tp->tg3_flags2 & TG3_FLG2_HW_TSO)
                tw32(SNDDATAI_MODE, SNDDATAI_MODE_ENABLE | 0x8);
@@ -8506,6 +8703,12 @@ static void tg3_timer(unsigned long __opaque)
                if (tp->tg3_flags2 & TG3_FLG2_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->tg3_flags & TG3_FLAG_USE_LINKCHG_REG) {
                        u32 mac_stat;
                        int phy_event;
@@ -8822,7 +9025,12 @@ static bool tg3_enable_msix(struct tg3 *tp)
        for (i = 0; i < tp->irq_max; i++)
                tp->napi[i].irq_vec = msix_ent[i].vector;
 
-       tp->dev->real_num_tx_queues = 1;
+       netif_set_real_num_tx_queues(tp->dev, 1);
+       rc = tp->irq_cnt > 1 ? tp->irq_cnt - 1 : 1;
+       if (netif_set_real_num_rx_queues(tp->dev, rc)) {
+               pci_disable_msix(tp->pdev);
+               return false;
+       }
        if (tp->irq_cnt > 1)
                tp->tg3_flags3 |= TG3_FLG3_ENABLE_RSS;
 
@@ -8857,7 +9065,8 @@ defcfg:
        if (!(tp->tg3_flags2 & TG3_FLG2_USING_MSIX)) {
                tp->irq_cnt = 1;
                tp->napi[0].irq_vec = tp->pdev->irq;
-               tp->dev->real_num_tx_queues = 1;
+               netif_set_real_num_tx_queues(tp->dev, 1);
+               netif_set_real_num_rx_queues(tp->dev, 1);
        }
 }
 
@@ -8916,6 +9125,8 @@ static int tg3_open(struct net_device *dev)
        if (err)
                goto err_out1;
 
+       tg3_napi_init(tp);
+
        tg3_napi_enable(tp);
 
        for (i = 0; i < tp->irq_cnt; i++) {
@@ -9003,6 +9214,7 @@ err_out3:
 
 err_out2:
        tg3_napi_disable(tp);
+       tg3_napi_fini(tp);
        tg3_free_consistent(tp);
 
 err_out1:
@@ -9050,6 +9262,8 @@ static int tg3_close(struct net_device *dev)
        memcpy(&tp->estats_prev, tg3_get_estats(tp),
               sizeof(tp->estats_prev));
 
+       tg3_napi_fini(tp);
+
        tg3_free_consistent(tp);
 
        tg3_set_power_state(tp, PCI_D3hot);
@@ -9593,6 +9807,9 @@ static int tg3_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
        if (netif_running(dev)) {
                cmd->speed = tp->link_config.active_speed;
                cmd->duplex = tp->link_config.active_duplex;
+       } else {
+               cmd->speed = SPEED_INVALID;
+               cmd->duplex = DUPLEX_INVALID;
        }
        cmd->phy_address = tp->phy_addr;
        cmd->transceiver = XCVR_INTERNAL;
@@ -9819,10 +10036,10 @@ static void tg3_get_ringparam(struct net_device *dev, struct ethtool_ringparam *
 {
        struct tg3 *tp = netdev_priv(dev);
 
-       ering->rx_max_pending = TG3_RX_RING_SIZE - 1;
+       ering->rx_max_pending = tp->rx_std_ring_mask;
        ering->rx_mini_max_pending = 0;
        if (tp->tg3_flags & TG3_FLAG_JUMBO_RING_ENABLE)
-               ering->rx_jumbo_max_pending = TG3_RX_JUMBO_RING_SIZE - 1;
+               ering->rx_jumbo_max_pending = tp->rx_jmb_ring_mask;
        else
                ering->rx_jumbo_max_pending = 0;
 
@@ -9843,8 +10060,8 @@ static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *e
        struct tg3 *tp = netdev_priv(dev);
        int i, irq_sync = 0, err = 0;
 
-       if ((ering->rx_pending > TG3_RX_RING_SIZE - 1) ||
-           (ering->rx_jumbo_pending > TG3_RX_JUMBO_RING_SIZE - 1) ||
+       if ((ering->rx_pending > tp->rx_std_ring_mask) ||
+           (ering->rx_jumbo_pending > tp->rx_jmb_ring_mask) ||
            (ering->tx_pending > TG3_TX_RING_SIZE - 1) ||
            (ering->tx_pending <= MAX_SKB_FRAGS) ||
            ((tp->tg3_flags2 & TG3_FLG2_TSO_BUG) &&
@@ -9914,8 +10131,7 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam
 
                if (!(phydev->supported & SUPPORTED_Pause) ||
                    (!(phydev->supported & SUPPORTED_Asym_Pause) &&
-                    ((epause->rx_pause && !epause->tx_pause) ||
-                     (!epause->rx_pause && epause->tx_pause))))
+                    (epause->rx_pause != epause->tx_pause)))
                        return -EINVAL;
 
                tp->link_config.flowctrl = 0;
@@ -10612,7 +10828,8 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode)
        tnapi = &tp->napi[0];
        rnapi = &tp->napi[0];
        if (tp->irq_cnt > 1) {
-               rnapi = &tp->napi[1];
+               if (tp->tg3_flags3 & TG3_FLG3_ENABLE_RSS)
+                       rnapi = &tp->napi[1];
                if (tp->tg3_flags3 & TG3_FLG3_ENABLE_TSS)
                        tnapi = &tp->napi[1];
        }
@@ -12329,6 +12546,11 @@ static int __devinit tg3_phy_probe(struct tg3 *tp)
                }
        }
 
+       if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718 ||
+           (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765 &&
+            tp->pci_chip_rev_id != CHIPREV_ID_57765_A0))
+               tp->phy_flags |= TG3_PHYFLG_EEE_CAP;
+
        if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES) &&
            !(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) &&
            !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) {
@@ -12497,44 +12719,49 @@ partno:
 
 out_not_found:
        kfree(vpd_data);
-       if (!tp->board_part_number[0])
+       if (tp->board_part_number[0])
                return;
 
 out_no_vpd:
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) {
+               if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717)
+                       strcpy(tp->board_part_number, "BCM5717");
+               else if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718)
+                       strcpy(tp->board_part_number, "BCM5718");
+               else
+                       goto nomatch;
+       } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780) {
+               if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_57780)
+                       strcpy(tp->board_part_number, "BCM57780");
+               else if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_57760)
+                       strcpy(tp->board_part_number, "BCM57760");
+               else if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_57790)
+                       strcpy(tp->board_part_number, "BCM57790");
+               else if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_57788)
+                       strcpy(tp->board_part_number, "BCM57788");
+               else
+                       goto nomatch;
+       } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) {
+               if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_57761)
+                       strcpy(tp->board_part_number, "BCM57761");
+               else if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_57765)
+                       strcpy(tp->board_part_number, "BCM57765");
+               else if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_57781)
+                       strcpy(tp->board_part_number, "BCM57781");
+               else if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_57785)
+                       strcpy(tp->board_part_number, "BCM57785");
+               else if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_57791)
+                       strcpy(tp->board_part_number, "BCM57791");
+               else if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_57795)
+                       strcpy(tp->board_part_number, "BCM57795");
+               else
+                       goto nomatch;
+       } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
                strcpy(tp->board_part_number, "BCM95906");
-       else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 &&
-                tp->pdev->device == TG3PCI_DEVICE_TIGON3_57780)
-               strcpy(tp->board_part_number, "BCM57780");
-       else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 &&
-                tp->pdev->device == TG3PCI_DEVICE_TIGON3_57760)
-               strcpy(tp->board_part_number, "BCM57760");
-       else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 &&
-                tp->pdev->device == TG3PCI_DEVICE_TIGON3_57790)
-               strcpy(tp->board_part_number, "BCM57790");
-       else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 &&
-                tp->pdev->device == TG3PCI_DEVICE_TIGON3_57788)
-               strcpy(tp->board_part_number, "BCM57788");
-       else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765 &&
-                tp->pdev->device == TG3PCI_DEVICE_TIGON3_57761)
-               strcpy(tp->board_part_number, "BCM57761");
-       else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765 &&
-                tp->pdev->device == TG3PCI_DEVICE_TIGON3_57765)
-               strcpy(tp->board_part_number, "BCM57765");
-       else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765 &&
-                tp->pdev->device == TG3PCI_DEVICE_TIGON3_57781)
-               strcpy(tp->board_part_number, "BCM57781");
-       else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765 &&
-                tp->pdev->device == TG3PCI_DEVICE_TIGON3_57785)
-               strcpy(tp->board_part_number, "BCM57785");
-       else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765 &&
-                tp->pdev->device == TG3PCI_DEVICE_TIGON3_57791)
-               strcpy(tp->board_part_number, "BCM57791");
-       else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765 &&
-                tp->pdev->device == TG3PCI_DEVICE_TIGON3_57795)
-               strcpy(tp->board_part_number, "BCM57795");
-       else
+       } else {
+nomatch:
                strcpy(tp->board_part_number, "none");
+       }
 }
 
 static int __devinit tg3_fw_img_is_valid(struct tg3 *tp, u32 offset)
@@ -12643,6 +12870,9 @@ static void __devinit tg3_read_sb_ver(struct tg3 *tp, u32 val)
        case TG3_EEPROM_SB_REVISION_5:
                offset = TG3_EEPROM_SB_F1R5_EDH_OFF;
                break;
+       case TG3_EEPROM_SB_REVISION_6:
+               offset = TG3_EEPROM_SB_F1R6_EDH_OFF;
+               break;
        default:
                return;
        }
@@ -12803,6 +13033,18 @@ static void inline vlan_features_add(struct net_device *dev, unsigned long flags
 #endif
 }
 
+static inline u32 tg3_rx_ret_ring_size(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)
+               return 4096;
+       else if ((tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) &&
+                !(tp->tg3_flags2 & TG3_FLG2_5780_CLASS))
+               return 1024;
+       else
+               return 512;
+}
+
 static int __devinit tg3_get_invariants(struct tg3 *tp)
 {
        static struct pci_device_id write_reorder_chipsets[] = {
@@ -12847,7 +13089,6 @@ 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_5719)
                        pci_read_config_dword(tp->pdev,
                                              TG3PCI_GEN2_PRODID_ASICREV,
@@ -13557,7 +13798,11 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
 #endif
        }
 
-       tp->rx_std_max_post = TG3_RX_RING_SIZE;
+       tp->rx_std_ring_mask = TG3_RX_STD_RING_SIZE(tp) - 1;
+       tp->rx_jmb_ring_mask = TG3_RX_JMB_RING_SIZE(tp) - 1;
+       tp->rx_ret_ring_mask = tg3_rx_ret_ring_size(tp) - 1;
+
+       tp->rx_std_max_post = tp->rx_std_ring_mask + 1;
 
        /* Increment the rx prod index on the rx std ring by at most
         * 8 for these chips to workaround hw errata.
@@ -14600,13 +14845,10 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
                tnapi->consmbox = rcvmbx;
                tnapi->prodmbox = sndmbx;
 
-               if (i) {
+               if (i)
                        tnapi->coal_now = HOSTCC_MODE_COAL_VEC1_NOW << (i - 1);
-                       netif_napi_add(dev, &tnapi->napi, tg3_poll_msix, 64);
-               } else {
+               else
                        tnapi->coal_now = HOSTCC_MODE_NOW;
-                       netif_napi_add(dev, &tnapi->napi, tg3_poll, 64);
-               }
 
                if (!(tp->tg3_flags & TG3_FLAG_SUPPORT_MSIX))
                        break;