b43: Fix PPC crash in rfkill polling on unload
[safe/jmp/linux-2.6] / drivers / net / tg3.c
index 5b8d6e0..ba5d3fe 100644 (file)
@@ -68,8 +68,8 @@
 
 #define DRV_MODULE_NAME                "tg3"
 #define PFX DRV_MODULE_NAME    ": "
-#define DRV_MODULE_VERSION     "3.100"
-#define DRV_MODULE_RELDATE     "August 25, 2009"
+#define DRV_MODULE_VERSION     "3.102"
+#define DRV_MODULE_RELDATE     "September 1, 2009"
 
 #define TG3_DEF_MAC_MODE       0
 #define TG3_DEF_RX_MODE                0
 #define TG3_DEF_RX_RING_PENDING                200
 #define TG3_RX_JUMBO_RING_SIZE         256
 #define TG3_DEF_RX_JUMBO_RING_PENDING  100
+#define TG3_RSS_INDIR_TBL_SIZE 128
 
 /* Do not place this n-ring entries value into the tp struct itself,
  * we really want to expose these constants to GCC so that modulo et
  * replace things like '% foo' with '& (foo - 1)'.
  */
 #define TG3_RX_RCB_RING_SIZE(tp)       \
-       ((tp->tg3_flags2 & TG3_FLG2_5705_PLUS) ?  512 : 1024)
+       (((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_JMB_MAP_SZ              TG3_RX_DMA_TO_MAP_SZ(TG3_RX_JMB_DMA_SZ)
 
 /* minimum number of free TX descriptors required to wake up TX process */
-#define TG3_TX_WAKEUP_THRESH(tp)               ((tp)->tx_pending / 4)
+#define TG3_TX_WAKEUP_THRESH(tnapi)            ((tnapi)->tx_pending / 4)
 
 #define TG3_RAW_IP_ALIGN 2
 
@@ -160,6 +162,7 @@ MODULE_FIRMWARE(FIRMWARE_TG3);
 MODULE_FIRMWARE(FIRMWARE_TG3TSO);
 MODULE_FIRMWARE(FIRMWARE_TG3TSO5);
 
+#define TG3_RSS_MIN_NUM_MSIX_VECS      2
 
 static int tg3_debug = -1;     /* -1 == use TG3_DEF_MSG_ENABLE as value */
 module_param(tg3_debug, int, 0);
@@ -613,33 +616,41 @@ static void tg3_ape_unlock(struct tg3 *tp, int locknum)
 
 static void tg3_disable_ints(struct tg3 *tp)
 {
+       int i;
+
        tw32(TG3PCI_MISC_HOST_CTRL,
             (tp->misc_host_ctrl | MISC_HOST_CTRL_MASK_PCI_INT));
-       tw32_mailbox_f(tp->napi[0].int_mbox, 0x00000001);
-}
-
-static inline void tg3_cond_int(struct tg3 *tp)
-{
-       if (!(tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) &&
-           (tp->napi[0].hw_status->status & SD_STATUS_UPDATED))
-               tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl | GRC_LCLCTRL_SETINT);
-       else
-               tw32(HOSTCC_MODE, tp->coalesce_mode |
-                    (HOSTCC_MODE_ENABLE | HOSTCC_MODE_NOW));
+       for (i = 0; i < tp->irq_max; i++)
+               tw32_mailbox_f(tp->napi[i].int_mbox, 0x00000001);
 }
 
 static void tg3_enable_ints(struct tg3 *tp)
 {
-       struct tg3_napi *tnapi = &tp->napi[0];
+       int i;
+       u32 coal_now = 0;
+
        tp->irq_sync = 0;
        wmb();
 
        tw32(TG3PCI_MISC_HOST_CTRL,
             (tp->misc_host_ctrl & ~MISC_HOST_CTRL_MASK_PCI_INT));
-       tw32_mailbox_f(tnapi->int_mbox, tnapi->last_tag << 24);
-       if (tp->tg3_flags2 & TG3_FLG2_1SHOT_MSI)
+
+       for (i = 0; i < tp->irq_cnt; i++) {
+               struct tg3_napi *tnapi = &tp->napi[i];
                tw32_mailbox_f(tnapi->int_mbox, tnapi->last_tag << 24);
-       tg3_cond_int(tp);
+               if (tp->tg3_flags2 & TG3_FLG2_1SHOT_MSI)
+                       tw32_mailbox_f(tnapi->int_mbox, tnapi->last_tag << 24);
+
+               coal_now |= tnapi->coal_now;
+       }
+
+       /* Force an initial interrupt */
+       if (!(tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) &&
+           (tp->napi[0].hw_status->status & SD_STATUS_UPDATED))
+               tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl | GRC_LCLCTRL_SETINT);
+       else
+               tw32(HOSTCC_MODE, tp->coalesce_mode |
+                    HOSTCC_MODE_ENABLE | coal_now);
 }
 
 static inline unsigned int tg3_has_work(struct tg3_napi *tnapi)
@@ -656,8 +667,8 @@ static inline unsigned int tg3_has_work(struct tg3_napi *tnapi)
                        work_exists = 1;
        }
        /* check for RX/TX work to do */
-       if (sblk->idx[0].tx_consumer != tp->tx_cons ||
-           sblk->idx[0].rx_producer != tp->rx_rcb_ptr)
+       if (sblk->idx[0].tx_consumer != tnapi->tx_cons ||
+           *(tnapi->rx_rcb_prod_idx) != tnapi->rx_rcb_ptr)
                work_exists = 1;
 
        return work_exists;
@@ -682,38 +693,56 @@ static void tg3_int_reenable(struct tg3_napi *tnapi)
        if (!(tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) &&
            tg3_has_work(tnapi))
                tw32(HOSTCC_MODE, tp->coalesce_mode |
-                    (HOSTCC_MODE_ENABLE | HOSTCC_MODE_NOW));
+                    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 */
-       napi_disable(&tp->napi[0].napi);
+       tg3_napi_disable(tp);
        netif_tx_disable(tp->dev);
 }
 
 static inline void tg3_netif_start(struct tg3 *tp)
 {
-       struct tg3_napi *tnapi = &tp->napi[0];
-       netif_wake_queue(tp->dev);
-       /* NOTE: unconditional netif_wake_queue is only appropriate
-        * so long as all callers are assured to have free tx slots
-        * (such as after tg3_init_hw)
+       /* 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)
         */
-       napi_enable(&tnapi->napi);
-       tnapi->hw_status->status |= SD_STATUS_UPDATED;
+       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 = tr32(TG3PCI_CLOCK_CTRL);
+       u32 clock_ctrl;
        u32 orig_clock_ctrl;
 
        if ((tp->tg3_flags & TG3_FLAG_CPMU_PRESENT) ||
            (tp->tg3_flags2 & TG3_FLG2_5780_CLASS))
                return;
 
+       clock_ctrl = tr32(TG3PCI_CLOCK_CTRL);
+
        orig_clock_ctrl = clock_ctrl;
        clock_ctrl &= (CLOCK_CTRL_FORCE_CLKRUN |
                       CLOCK_CTRL_CLKRUN_OENABLE |
@@ -753,7 +782,7 @@ static int tg3_readphy(struct tg3 *tp, int reg, u32 *val)
 
        *val = 0x0;
 
-       frame_val  = ((PHY_ADDR << MI_COM_PHY_ADDR_SHIFT) &
+       frame_val  = ((tp->phy_addr << MI_COM_PHY_ADDR_SHIFT) &
                      MI_COM_PHY_ADDR_MASK);
        frame_val |= ((reg << MI_COM_REG_ADDR_SHIFT) &
                      MI_COM_REG_ADDR_MASK);
@@ -804,7 +833,7 @@ static int tg3_writephy(struct tg3 *tp, int reg, u32 val)
                udelay(80);
        }
 
-       frame_val  = ((PHY_ADDR << MI_COM_PHY_ADDR_SHIFT) &
+       frame_val  = ((tp->phy_addr << MI_COM_PHY_ADDR_SHIFT) &
                      MI_COM_PHY_ADDR_MASK);
        frame_val |= ((reg << MI_COM_REG_ADDR_SHIFT) &
                      MI_COM_REG_ADDR_MASK);
@@ -873,11 +902,12 @@ static int tg3_mdio_read(struct mii_bus *bp, int mii_id, int reg)
        struct tg3 *tp = bp->priv;
        u32 val;
 
-       if (tp->tg3_flags3 & TG3_FLG3_MDIOBUS_PAUSED)
-               return -EAGAIN;
+       spin_lock_bh(&tp->lock);
 
        if (tg3_readphy(tp, reg, &val))
-               return -EIO;
+               val = -EIO;
+
+       spin_unlock_bh(&tp->lock);
 
        return val;
 }
@@ -885,14 +915,16 @@ static int tg3_mdio_read(struct mii_bus *bp, int mii_id, int reg)
 static int tg3_mdio_write(struct mii_bus *bp, int mii_id, int reg, u16 val)
 {
        struct tg3 *tp = bp->priv;
+       u32 ret = 0;
 
-       if (tp->tg3_flags3 & TG3_FLG3_MDIOBUS_PAUSED)
-               return -EAGAIN;
+       spin_lock_bh(&tp->lock);
 
        if (tg3_writephy(tp, reg, val))
-               return -EIO;
+               ret = -EIO;
 
-       return 0;
+       spin_unlock_bh(&tp->lock);
+
+       return ret;
 }
 
 static int tg3_mdio_reset(struct mii_bus *bp)
@@ -982,30 +1014,30 @@ static void tg3_mdio_config_5785(struct tg3 *tp)
 
 static void tg3_mdio_start(struct tg3 *tp)
 {
-       if (tp->tg3_flags3 & TG3_FLG3_MDIOBUS_INITED) {
-               mutex_lock(&tp->mdio_bus->mdio_lock);
-               tp->tg3_flags3 &= ~TG3_FLG3_MDIOBUS_PAUSED;
-               mutex_unlock(&tp->mdio_bus->mdio_lock);
-       }
-
        tp->mi_mode &= ~MAC_MI_MODE_AUTO_POLL;
        tw32_f(MAC_MI_MODE, tp->mi_mode);
        udelay(80);
 
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) {
+               u32 funcnum, is_serdes;
+
+               funcnum = tr32(TG3_CPMU_STATUS) & TG3_CPMU_STATUS_PCIE_FUNC;
+               if (funcnum)
+                       tp->phy_addr = 2;
+               else
+                       tp->phy_addr = 1;
+
+               is_serdes = tr32(SG_DIG_STATUS) & SG_DIG_IS_SERDES;
+               if (is_serdes)
+                       tp->phy_addr += 7;
+       } else
+               tp->phy_addr = PHY_ADDR;
+
        if ((tp->tg3_flags3 & TG3_FLG3_MDIOBUS_INITED) &&
            GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785)
                tg3_mdio_config_5785(tp);
 }
 
-static void tg3_mdio_stop(struct tg3 *tp)
-{
-       if (tp->tg3_flags3 & TG3_FLG3_MDIOBUS_INITED) {
-               mutex_lock(&tp->mdio_bus->mdio_lock);
-               tp->tg3_flags3 |= TG3_FLG3_MDIOBUS_PAUSED;
-               mutex_unlock(&tp->mdio_bus->mdio_lock);
-       }
-}
-
 static int tg3_mdio_init(struct tg3 *tp)
 {
        int i;
@@ -1097,7 +1129,6 @@ static void tg3_mdio_fini(struct tg3 *tp)
                tp->tg3_flags3 &= ~TG3_FLG3_MDIOBUS_INITED;
                mdiobus_unregister(tp->mdio_bus);
                mdiobus_free(tp->mdio_bus);
-               tp->tg3_flags3 &= ~TG3_FLG3_MDIOBUS_PAUSED;
        }
 }
 
@@ -1319,7 +1350,7 @@ static void tg3_adjust_link(struct net_device *dev)
        struct tg3 *tp = netdev_priv(dev);
        struct phy_device *phydev = tp->mdio_bus->phy_map[PHY_ADDR];
 
-       spin_lock(&tp->lock);
+       spin_lock_bh(&tp->lock);
 
        mac_mode = tp->mac_mode & ~(MAC_MODE_PORT_MODE_MASK |
                                    MAC_MODE_HALF_DUPLEX);
@@ -1387,7 +1418,7 @@ static void tg3_adjust_link(struct net_device *dev)
        tp->link_config.active_speed = phydev->speed;
        tp->link_config.active_duplex = phydev->duplex;
 
-       spin_unlock(&tp->lock);
+       spin_unlock_bh(&tp->lock);
 
        if (linkmesg)
                tg3_link_report(tp);
@@ -1967,8 +1998,9 @@ static void tg3_frob_aux_power(struct tg3 *tp)
        if ((tp->tg3_flags2 & TG3_FLG2_IS_NIC) == 0)
                return;
 
-       if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) ||
-           (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714)) {
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) {
                struct net_device *dev_peer;
 
                dev_peer = pci_get_drvdata(tp->pdev_peer);
@@ -4269,11 +4301,11 @@ static void tg3_tx_recover(struct tg3 *tp)
        spin_unlock(&tp->lock);
 }
 
-static inline u32 tg3_tx_avail(struct tg3 *tp)
+static inline u32 tg3_tx_avail(struct tg3_napi *tnapi)
 {
        smp_mb();
-       return (tp->tx_pending -
-               ((tp->tx_prod - tp->tx_cons) & (TG3_TX_RING_SIZE - 1)));
+       return tnapi->tx_pending -
+              ((tnapi->tx_prod - tnapi->tx_cons) & (TG3_TX_RING_SIZE - 1));
 }
 
 /* Tigon3 never reports partial packet sends.  So we do not
@@ -4284,10 +4316,17 @@ static void tg3_tx(struct tg3_napi *tnapi)
 {
        struct tg3 *tp = tnapi->tp;
        u32 hw_idx = tnapi->hw_status->idx[0].tx_consumer;
-       u32 sw_idx = tp->tx_cons;
+       u32 sw_idx = tnapi->tx_cons;
+       struct netdev_queue *txq;
+       int index = tnapi - tp->napi;
+
+       if (tp->tg3_flags2 & TG3_FLG2_USING_MSIX)
+               index--;
+
+       txq = netdev_get_tx_queue(tp->dev, index);
 
        while (sw_idx != hw_idx) {
-               struct tx_ring_info *ri = &tp->tx_buffers[sw_idx];
+               struct tx_ring_info *ri = &tnapi->tx_buffers[sw_idx];
                struct sk_buff *skb = ri->skb;
                int i, tx_bug = 0;
 
@@ -4303,7 +4342,7 @@ static void tg3_tx(struct tg3_napi *tnapi)
                sw_idx = NEXT_TX(sw_idx);
 
                for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
-                       ri = &tp->tx_buffers[sw_idx];
+                       ri = &tnapi->tx_buffers[sw_idx];
                        if (unlikely(ri->skb != NULL || sw_idx == hw_idx))
                                tx_bug = 1;
                        sw_idx = NEXT_TX(sw_idx);
@@ -4317,7 +4356,7 @@ static void tg3_tx(struct tg3_napi *tnapi)
                }
        }
 
-       tp->tx_cons = sw_idx;
+       tnapi->tx_cons = sw_idx;
 
        /* Need to make the tx_cons update visible to tg3_start_xmit()
         * before checking for netif_queue_stopped().  Without the
@@ -4326,13 +4365,13 @@ static void tg3_tx(struct tg3_napi *tnapi)
         */
        smp_mb();
 
-       if (unlikely(netif_queue_stopped(tp->dev) &&
-                    (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH(tp)))) {
-               netif_tx_lock(tp->dev);
-               if (netif_queue_stopped(tp->dev) &&
-                   (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH(tp)))
-                       netif_wake_queue(tp->dev);
-               netif_tx_unlock(tp->dev);
+       if (unlikely(netif_tx_queue_stopped(txq) &&
+                    (tg3_tx_avail(tnapi) > TG3_TX_WAKEUP_THRESH(tnapi)))) {
+               __netif_tx_lock(txq, smp_processor_id());
+               if (netif_tx_queue_stopped(txq) &&
+                   (tg3_tx_avail(tnapi) > TG3_TX_WAKEUP_THRESH(tnapi)))
+                       netif_tx_wake_queue(txq);
+               __netif_tx_unlock(txq);
        }
 }
 
@@ -4480,12 +4519,12 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget)
 {
        struct tg3 *tp = tnapi->tp;
        u32 work_mask, rx_std_posted = 0;
-       u32 sw_idx = tp->rx_rcb_ptr;
+       u32 sw_idx = tnapi->rx_rcb_ptr;
        u16 hw_idx;
        int received;
        struct tg3_rx_prodring_set *tpr = &tp->prodring[0];
 
-       hw_idx = tnapi->hw_status->idx[0].rx_producer;
+       hw_idx = *(tnapi->rx_rcb_prod_idx);
        /*
         * We need to order the read of hw_idx and the read of
         * the opaque cookie.
@@ -4494,7 +4533,7 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget)
        work_mask = 0;
        received = 0;
        while (sw_idx != hw_idx && budget > 0) {
-               struct tg3_rx_buffer_desc *desc = &tp->rx_rcb[sw_idx];
+               struct tg3_rx_buffer_desc *desc = &tnapi->rx_rcb[sw_idx];
                unsigned int len;
                struct sk_buff *skb;
                dma_addr_t dma_addr;
@@ -4616,14 +4655,14 @@ next_pkt_nopost:
 
                /* Refresh hw_idx to see if there is new work */
                if (sw_idx == hw_idx) {
-                       hw_idx = tnapi->hw_status->idx[0].rx_producer;
+                       hw_idx = *(tnapi->rx_rcb_prod_idx);
                        rmb();
                }
        }
 
        /* ACK the status ring. */
-       tp->rx_rcb_ptr = sw_idx;
-       tw32_rx_mbox(MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW, sw_idx);
+       tnapi->rx_rcb_ptr = sw_idx;
+       tw32_rx_mbox(tnapi->consmbox, sw_idx);
 
        /* Refill RX ring(s). */
        if (work_mask & RXD_OPAQUE_RING_STD) {
@@ -4668,7 +4707,7 @@ static int tg3_poll_work(struct tg3_napi *tnapi, int work_done, int budget)
        }
 
        /* run TX completion thread */
-       if (sblk->idx[0].tx_consumer != tp->tx_cons) {
+       if (tnapi->hw_status->idx[0].tx_consumer != tnapi->tx_cons) {
                tg3_tx(tnapi);
                if (unlikely(tp->tg3_flags & TG3_FLAG_TX_RECOVERY_PENDING))
                        return work_done;
@@ -4678,7 +4717,7 @@ static int tg3_poll_work(struct tg3_napi *tnapi, int work_done, int budget)
         * All RX "locking" is done by ensuring outside
         * code synchronizes with tg3->napi.poll()
         */
-       if (sblk->idx[0].rx_producer != tp->rx_rcb_ptr)
+       if (*(tnapi->rx_rcb_prod_idx) != tnapi->rx_rcb_ptr)
                work_done += tg3_rx(tnapi, budget - work_done);
 
        return work_done;
@@ -4729,12 +4768,15 @@ tx_recovery:
 
 static void tg3_irq_quiesce(struct tg3 *tp)
 {
+       int i;
+
        BUG_ON(tp->irq_sync);
 
        tp->irq_sync = 1;
        smp_mb();
 
-       synchronize_irq(tp->pdev->irq);
+       for (i = 0; i < tp->irq_cnt; i++)
+               synchronize_irq(tp->napi[i].irq_vec);
 }
 
 static inline int tg3_irq_sync(struct tg3 *tp)
@@ -4768,7 +4810,8 @@ static irqreturn_t tg3_msi_1shot(int irq, void *dev_id)
        struct tg3 *tp = tnapi->tp;
 
        prefetch(tnapi->hw_status);
-       prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]);
+       if (tnapi->rx_rcb)
+               prefetch(&tnapi->rx_rcb[tnapi->rx_rcb_ptr]);
 
        if (likely(!tg3_irq_sync(tp)))
                napi_schedule(&tnapi->napi);
@@ -4786,7 +4829,8 @@ static irqreturn_t tg3_msi(int irq, void *dev_id)
        struct tg3 *tp = tnapi->tp;
 
        prefetch(tnapi->hw_status);
-       prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]);
+       if (tnapi->rx_rcb)
+               prefetch(&tnapi->rx_rcb[tnapi->rx_rcb_ptr]);
        /*
         * Writing any value to intr-mbox-0 clears PCI INTA# and
         * chip-internal interrupt pending events.
@@ -4837,7 +4881,7 @@ static irqreturn_t tg3_interrupt(int irq, void *dev_id)
                goto out;
        sblk->status &= ~SD_STATUS_UPDATED;
        if (likely(tg3_has_work(tnapi))) {
-               prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]);
+               prefetch(&tnapi->rx_rcb[tnapi->rx_rcb_ptr]);
                napi_schedule(&tnapi->napi);
        } else {
                /* No work, shared interrupt perhaps?  re-enable
@@ -4894,7 +4938,7 @@ static irqreturn_t tg3_interrupt_tagged(int irq, void *dev_id)
        if (tg3_irq_sync(tp))
                goto out;
 
-       prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]);
+       prefetch(&tnapi->rx_rcb[tnapi->rx_rcb_ptr]);
 
        napi_schedule(&tnapi->napi);
 
@@ -4937,7 +4981,7 @@ static int tg3_restart_hw(struct tg3 *tp, int reset_phy)
                tg3_full_unlock(tp);
                del_timer_sync(&tp->timer);
                tp->irq_sync = 0;
-               napi_enable(&tp->napi[0].napi);
+               tg3_napi_enable(tp);
                dev_close(tp->dev);
                tg3_full_lock(tp, 0);
        }
@@ -4947,9 +4991,11 @@ static int tg3_restart_hw(struct tg3 *tp, int reset_phy)
 #ifdef CONFIG_NET_POLL_CONTROLLER
 static void tg3_poll_controller(struct net_device *dev)
 {
+       int i;
        struct tg3 *tp = netdev_priv(dev);
 
-       tg3_interrupt(tp->pdev->irq, dev);
+       for (i = 0; i < tp->irq_cnt; i++)
+               tg3_interrupt(tp->napi[i].irq_vec, dev);
 }
 #endif
 
@@ -5044,13 +5090,14 @@ static inline int tg3_40bit_overflow_test(struct tg3 *tp, dma_addr_t mapping,
 #endif
 }
 
-static void tg3_set_txd(struct tg3 *, int, dma_addr_t, int, u32, u32);
+static void tg3_set_txd(struct tg3_napi *, int, dma_addr_t, int, u32, u32);
 
 /* Workaround 4GB and 40-bit hardware DMA bugs. */
 static int tigon3_dma_hwbug_workaround(struct tg3 *tp, struct sk_buff *skb,
                                       u32 last_plus_one, u32 *start,
                                       u32 base_flags, u32 mss)
 {
+       struct tg3_napi *tnapi = &tp->napi[0];
        struct sk_buff *new_skb;
        dma_addr_t new_addr = 0;
        u32 entry = *start;
@@ -5085,7 +5132,7 @@ static int tigon3_dma_hwbug_workaround(struct tg3 *tp, struct sk_buff *skb,
                        dev_kfree_skb(new_skb);
                        new_skb = NULL;
                } else {
-                       tg3_set_txd(tp, entry, new_addr, new_skb->len,
+                       tg3_set_txd(tnapi, entry, new_addr, new_skb->len,
                                    base_flags, 1 | (mss << 1));
                        *start = NEXT_TX(entry);
                }
@@ -5094,11 +5141,10 @@ static int tigon3_dma_hwbug_workaround(struct tg3 *tp, struct sk_buff *skb,
        /* Now clean up the sw ring entries. */
        i = 0;
        while (entry != last_plus_one) {
-               if (i == 0) {
-                       tp->tx_buffers[entry].skb = new_skb;
-               } else {
-                       tp->tx_buffers[entry].skb = NULL;
-               }
+               if (i == 0)
+                       tnapi->tx_buffers[entry].skb = new_skb;
+               else
+                       tnapi->tx_buffers[entry].skb = NULL;
                entry = NEXT_TX(entry);
                i++;
        }
@@ -5109,11 +5155,11 @@ static int tigon3_dma_hwbug_workaround(struct tg3 *tp, struct sk_buff *skb,
        return ret;
 }
 
-static void tg3_set_txd(struct tg3 *tp, int entry,
+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 = &tp->tx_ring[entry];
+       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;
@@ -5135,23 +5181,29 @@ static void tg3_set_txd(struct tg3 *tp, int entry,
 /* hard_start_xmit for devices that don't have any bugs and
  * support TG3_FLG2_HW_TSO_2 only.
  */
-static int tg3_start_xmit(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;
        struct skb_shared_info *sp;
        dma_addr_t mapping;
+       struct tg3_napi *tnapi;
+       struct netdev_queue *txq;
 
-       len = skb_headlen(skb);
+       txq = netdev_get_tx_queue(dev, skb_get_queue_mapping(skb));
+       tnapi = &tp->napi[skb_get_queue_mapping(skb)];
+       if (tp->tg3_flags2 & TG3_FLG2_USING_MSIX)
+               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(tp) <= (skb_shinfo(skb)->nr_frags + 1))) {
-               if (!netif_queue_stopped(dev)) {
-                       netif_stop_queue(dev);
+       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. */
                        printk(KERN_ERR PFX "%s: BUG! Tx Ring full when "
@@ -5160,11 +5212,12 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
                return NETDEV_TX_BUSY;
        }
 
-       entry = tp->tx_prod;
+       entry = tnapi->tx_prod;
        base_flags = 0;
        mss = 0;
        if ((mss = skb_shinfo(skb)->gso_size) != 0) {
                int tcp_opt_len, ip_tcp_len;
+               u32 hdrlen;
 
                if (skb_header_cloned(skb) &&
                    pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) {
@@ -5173,7 +5226,7 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
                }
 
                if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6)
-                       mss |= (skb_headlen(skb) - ETH_HLEN) << 9;
+                       hdrlen = skb_headlen(skb) - ETH_HLEN;
                else {
                        struct iphdr *iph = ip_hdr(skb);
 
@@ -5182,9 +5235,17 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
                        iph->check = 0;
                        iph->tot_len = htons(mss + ip_tcp_len + tcp_opt_len);
-                       mss |= (ip_tcp_len + tcp_opt_len) << 9;
+                       hdrlen = ip_tcp_len + tcp_opt_len;
                }
 
+               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) {
+                       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);
 
@@ -5208,9 +5269,15 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
        mapping = sp->dma_head;
 
-       tp->tx_buffers[entry].skb = skb;
+       tnapi->tx_buffers[entry].skb = skb;
+
+       len = skb_headlen(skb);
 
-       tg3_set_txd(tp, entry, mapping, len, base_flags,
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 &&
+           !mss && skb->len > ETH_DATA_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);
@@ -5225,9 +5292,9 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
                        len = frag->size;
                        mapping = sp->dma_maps[i];
-                       tp->tx_buffers[entry].skb = NULL;
+                       tnapi->tx_buffers[entry].skb = NULL;
 
-                       tg3_set_txd(tp, entry, mapping, len,
+                       tg3_set_txd(tnapi, entry, mapping, len,
                                    base_flags, (i == last) | (mss << 1));
 
                        entry = NEXT_TX(entry);
@@ -5235,13 +5302,13 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
        }
 
        /* Packets are ready, update Tx producer idx local and on card. */
-       tw32_tx_mbox((MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW), entry);
+       tw32_tx_mbox(tnapi->prodmbox, entry);
 
-       tp->tx_prod = entry;
-       if (unlikely(tg3_tx_avail(tp) <= (MAX_SKB_FRAGS + 1))) {
-               netif_stop_queue(dev);
-               if (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH(tp))
-                       netif_wake_queue(tp->dev);
+       tnapi->tx_prod = entry;
+       if (unlikely(tg3_tx_avail(tnapi) <= (MAX_SKB_FRAGS + 1))) {
+               netif_tx_stop_queue(txq);
+               if (tg3_tx_avail(tnapi) > TG3_TX_WAKEUP_THRESH(tnapi))
+                       netif_tx_wake_queue(txq);
        }
 
 out_unlock:
@@ -5250,7 +5317,8 @@ out_unlock:
        return NETDEV_TX_OK;
 }
 
-static int tg3_start_xmit_dma_bug(struct sk_buff *, struct net_device *);
+static netdev_tx_t tg3_start_xmit_dma_bug(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.
@@ -5258,11 +5326,12 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *, struct net_device *);
 static int tg3_tso_bug(struct tg3 *tp, struct sk_buff *skb)
 {
        struct sk_buff *segs, *nskb;
+       u32 frag_cnt_est = skb_shinfo(skb)->gso_segs * 3;
 
        /* Estimate the number of fragments in the worst case */
-       if (unlikely(tg3_tx_avail(tp) <= (skb_shinfo(skb)->gso_segs * 3))) {
+       if (unlikely(tg3_tx_avail(&tp->napi[0]) <= frag_cnt_est)) {
                netif_stop_queue(tp->dev);
-               if (tg3_tx_avail(tp) <= (skb_shinfo(skb)->gso_segs * 3))
+               if (tg3_tx_avail(&tp->napi[0]) <= frag_cnt_est)
                        return NETDEV_TX_BUSY;
 
                netif_wake_queue(tp->dev);
@@ -5288,13 +5357,15 @@ tg3_tso_bug_end:
 /* hard_start_xmit for devices that have the 4G bug and/or 40-bit bug and
  * support TG3_FLG2_HW_TSO_1 or firmware TSO only.
  */
-static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev)
+static netdev_tx_t tg3_start_xmit_dma_bug(struct sk_buff *skb,
+                                         struct net_device *dev)
 {
        struct tg3 *tp = netdev_priv(dev);
        u32 len, entry, base_flags, mss;
        struct skb_shared_info *sp;
        int would_hit_hwbug;
        dma_addr_t mapping;
+       struct tg3_napi *tnapi = &tp->napi[0];
 
        len = skb_headlen(skb);
 
@@ -5303,7 +5374,7 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev)
         * interrupt.  Furthermore, IRQ processing runs lockless so we have
         * no IRQ context deadlocks to worry about either.  Rejoice!
         */
-       if (unlikely(tg3_tx_avail(tp) <= (skb_shinfo(skb)->nr_frags + 1))) {
+       if (unlikely(tg3_tx_avail(tnapi) <= (skb_shinfo(skb)->nr_frags + 1))) {
                if (!netif_queue_stopped(dev)) {
                        netif_stop_queue(dev);
 
@@ -5314,7 +5385,7 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev)
                return NETDEV_TX_BUSY;
        }
 
-       entry = tp->tx_prod;
+       entry = tnapi->tx_prod;
        base_flags = 0;
        if (skb->ip_summed == CHECKSUM_PARTIAL)
                base_flags |= TXD_FLAG_TCPUDP_CSUM;
@@ -5384,7 +5455,7 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev)
 
        mapping = sp->dma_head;
 
-       tp->tx_buffers[entry].skb = skb;
+       tnapi->tx_buffers[entry].skb = skb;
 
        would_hit_hwbug = 0;
 
@@ -5393,7 +5464,7 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev)
        else if (tg3_4g_overflow_test(mapping, len))
                would_hit_hwbug = 1;
 
-       tg3_set_txd(tp, entry, mapping, len, base_flags,
+       tg3_set_txd(tnapi, entry, mapping, len, base_flags,
                    (skb_shinfo(skb)->nr_frags == 0) | (mss << 1));
 
        entry = NEXT_TX(entry);
@@ -5409,7 +5480,7 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev)
                        len = frag->size;
                        mapping = sp->dma_maps[i];
 
-                       tp->tx_buffers[entry].skb = NULL;
+                       tnapi->tx_buffers[entry].skb = NULL;
 
                        if (tg3_4g_overflow_test(mapping, len))
                                would_hit_hwbug = 1;
@@ -5418,10 +5489,10 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev)
                                would_hit_hwbug = 1;
 
                        if (tp->tg3_flags2 & TG3_FLG2_HW_TSO)
-                               tg3_set_txd(tp, entry, mapping, len,
+                               tg3_set_txd(tnapi, entry, mapping, len,
                                            base_flags, (i == last)|(mss << 1));
                        else
-                               tg3_set_txd(tp, entry, mapping, len,
+                               tg3_set_txd(tnapi, entry, mapping, len,
                                            base_flags, (i == last));
 
                        entry = NEXT_TX(entry);
@@ -5446,12 +5517,12 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev)
        }
 
        /* Packets are ready, update Tx producer idx local and on card. */
-       tw32_tx_mbox((MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW), entry);
+       tw32_tx_mbox(MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW, entry);
 
-       tp->tx_prod = entry;
-       if (unlikely(tg3_tx_avail(tp) <= (MAX_SKB_FRAGS + 1))) {
+       tnapi->tx_prod = entry;
+       if (unlikely(tg3_tx_avail(tnapi) <= (MAX_SKB_FRAGS + 1))) {
                netif_stop_queue(dev);
-               if (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH(tp))
+               if (tg3_tx_avail(tnapi) > TG3_TX_WAKEUP_THRESH(tnapi))
                        netif_wake_queue(tp->dev);
        }
 
@@ -5522,8 +5593,8 @@ static int tg3_change_mtu(struct net_device *dev, int new_mtu)
 static void tg3_rx_prodring_free(struct tg3 *tp,
                                 struct tg3_rx_prodring_set *tpr)
 {
-       struct ring_info *rxp;
        int i;
+       struct ring_info *rxp;
 
        for (i = 0; i < TG3_RX_RING_SIZE; i++) {
                rxp = &tpr->rx_std_buffers[i];
@@ -5710,27 +5781,34 @@ err_out:
  */
 static void tg3_free_rings(struct tg3 *tp)
 {
-       int i;
+       int i, j;
 
-       for (i = 0; i < TG3_TX_RING_SIZE; ) {
-               struct tx_ring_info *txp;
-               struct sk_buff *skb;
-
-               txp = &tp->tx_buffers[i];
-               skb = txp->skb;
+       for (j = 0; j < tp->irq_cnt; j++) {
+               struct tg3_napi *tnapi = &tp->napi[j];
 
-               if (skb == NULL) {
-                       i++;
+               if (!tnapi->tx_buffers)
                        continue;
-               }
 
-               skb_dma_unmap(&tp->pdev->dev, skb, DMA_TO_DEVICE);
+               for (i = 0; i < TG3_TX_RING_SIZE; ) {
+                       struct tx_ring_info *txp;
+                       struct sk_buff *skb;
+
+                       txp = &tnapi->tx_buffers[i];
+                       skb = txp->skb;
+
+                       if (skb == NULL) {
+                               i++;
+                               continue;
+                       }
+
+                       skb_dma_unmap(&tp->pdev->dev, skb, DMA_TO_DEVICE);
 
-               txp->skb = NULL;
+                       txp->skb = NULL;
 
-               i += skb_shinfo(skb)->nr_frags + 1;
+                       i += skb_shinfo(skb)->nr_frags + 1;
 
-               dev_kfree_skb_any(skb);
+                       dev_kfree_skb_any(skb);
+               }
        }
 
        tg3_rx_prodring_free(tp, &tp->prodring[0]);
@@ -5745,12 +5823,29 @@ static void tg3_free_rings(struct tg3 *tp)
  */
 static int tg3_init_rings(struct tg3 *tp)
 {
+       int i;
+
        /* Free up all the SKBs. */
        tg3_free_rings(tp);
 
-       /* Zero out all descriptors. */
-       memset(tp->rx_rcb, 0, TG3_RX_RCB_RING_BYTES(tp));
-       memset(tp->tx_ring, 0, TG3_TX_RING_BYTES);
+       for (i = 0; i < tp->irq_cnt; i++) {
+               struct tg3_napi *tnapi = &tp->napi[i];
+
+               tnapi->last_tag = 0;
+               tnapi->last_irq_tag = 0;
+               tnapi->hw_status->status = 0;
+               tnapi->hw_status->status_tag = 0;
+               memset(tnapi->hw_status, 0, TG3_HW_STATUS_SIZE);
+
+               tnapi->tx_prod = 0;
+               tnapi->tx_cons = 0;
+               if (tnapi->tx_ring)
+                       memset(tnapi->tx_ring, 0, TG3_TX_RING_BYTES);
+
+               tnapi->rx_rcb_ptr = 0;
+               if (tnapi->rx_rcb)
+                       memset(tnapi->rx_rcb, 0, TG3_RX_RCB_RING_BYTES(tp));
+       }
 
        return tg3_rx_prodring_alloc(tp, &tp->prodring[0]);
 }
@@ -5761,31 +5856,41 @@ static int tg3_init_rings(struct tg3 *tp)
  */
 static void tg3_free_consistent(struct tg3 *tp)
 {
-       struct tg3_napi *tnapi = &tp->napi[0];
+       int i;
 
-       kfree(tp->tx_buffers);
-       tp->tx_buffers = NULL;
-       if (tp->rx_rcb) {
-               pci_free_consistent(tp->pdev, TG3_RX_RCB_RING_BYTES(tp),
-                                   tp->rx_rcb, tp->rx_rcb_mapping);
-               tp->rx_rcb = NULL;
-       }
-       if (tp->tx_ring) {
-               pci_free_consistent(tp->pdev, TG3_TX_RING_BYTES,
-                       tp->tx_ring, tp->tx_desc_mapping);
-               tp->tx_ring = NULL;
-       }
-       if (tnapi->hw_status) {
-               pci_free_consistent(tp->pdev, TG3_HW_STATUS_SIZE,
-                                   tnapi->hw_status,
-                                   tnapi->status_mapping);
-               tnapi->hw_status = NULL;
+       for (i = 0; i < tp->irq_cnt; i++) {
+               struct tg3_napi *tnapi = &tp->napi[i];
+
+               if (tnapi->tx_ring) {
+                       pci_free_consistent(tp->pdev, TG3_TX_RING_BYTES,
+                               tnapi->tx_ring, tnapi->tx_desc_mapping);
+                       tnapi->tx_ring = NULL;
+               }
+
+               kfree(tnapi->tx_buffers);
+               tnapi->tx_buffers = NULL;
+
+               if (tnapi->rx_rcb) {
+                       pci_free_consistent(tp->pdev, TG3_RX_RCB_RING_BYTES(tp),
+                                           tnapi->rx_rcb,
+                                           tnapi->rx_rcb_mapping);
+                       tnapi->rx_rcb = NULL;
+               }
+
+               if (tnapi->hw_status) {
+                       pci_free_consistent(tp->pdev, TG3_HW_STATUS_SIZE,
+                                           tnapi->hw_status,
+                                           tnapi->status_mapping);
+                       tnapi->hw_status = NULL;
+               }
        }
+
        if (tp->hw_stats) {
                pci_free_consistent(tp->pdev, sizeof(struct tg3_hw_stats),
                                    tp->hw_stats, tp->stats_mapping);
                tp->hw_stats = NULL;
        }
+
        tg3_rx_prodring_fini(tp, &tp->prodring[0]);
 }
 
@@ -5795,34 +5900,11 @@ static void tg3_free_consistent(struct tg3 *tp)
  */
 static int tg3_alloc_consistent(struct tg3 *tp)
 {
-       struct tg3_napi *tnapi = &tp->napi[0];
+       int i;
 
        if (tg3_rx_prodring_init(tp, &tp->prodring[0]))
                return -ENOMEM;
 
-       tp->tx_buffers = kzalloc(sizeof(struct tx_ring_info) *
-                                TG3_TX_RING_SIZE, GFP_KERNEL);
-       if (!tp->tx_buffers)
-               goto err_out;
-
-       tp->rx_rcb = pci_alloc_consistent(tp->pdev, TG3_RX_RCB_RING_BYTES(tp),
-                                         &tp->rx_rcb_mapping);
-       if (!tp->rx_rcb)
-               goto err_out;
-
-       tp->tx_ring = pci_alloc_consistent(tp->pdev, TG3_TX_RING_BYTES,
-                                          &tp->tx_desc_mapping);
-       if (!tp->tx_ring)
-               goto err_out;
-
-       tnapi->hw_status = pci_alloc_consistent(tp->pdev,
-                                               TG3_HW_STATUS_SIZE,
-                                               &tnapi->status_mapping);
-       if (!tnapi->hw_status)
-               goto err_out;
-
-       memset(tnapi->hw_status, 0, TG3_HW_STATUS_SIZE);
-
        tp->hw_stats = pci_alloc_consistent(tp->pdev,
                                            sizeof(struct tg3_hw_stats),
                                            &tp->stats_mapping);
@@ -5831,6 +5913,67 @@ static int tg3_alloc_consistent(struct tg3 *tp)
 
        memset(tp->hw_stats, 0, sizeof(struct tg3_hw_stats));
 
+       for (i = 0; i < tp->irq_cnt; i++) {
+               struct tg3_napi *tnapi = &tp->napi[i];
+               struct tg3_hw_status *sblk;
+
+               tnapi->hw_status = pci_alloc_consistent(tp->pdev,
+                                                       TG3_HW_STATUS_SIZE,
+                                                       &tnapi->status_mapping);
+               if (!tnapi->hw_status)
+                       goto err_out;
+
+               memset(tnapi->hw_status, 0, TG3_HW_STATUS_SIZE);
+               sblk = tnapi->hw_status;
+
+               /*
+                * When RSS is enabled, the status block format changes
+                * slightly.  The "rx_jumbo_consumer", "reserved",
+                * and "rx_mini_consumer" members get mapped to the
+                * other three rx return ring producer indexes.
+                */
+               switch (i) {
+               default:
+                       tnapi->rx_rcb_prod_idx = &sblk->idx[0].rx_producer;
+                       break;
+               case 2:
+                       tnapi->rx_rcb_prod_idx = &sblk->rx_jumbo_consumer;
+                       break;
+               case 3:
+                       tnapi->rx_rcb_prod_idx = &sblk->reserved;
+                       break;
+               case 4:
+                       tnapi->rx_rcb_prod_idx = &sblk->rx_mini_consumer;
+                       break;
+               }
+
+               /*
+                * If multivector RSS is enabled, vector 0 does not handle
+                * rx or tx interrupts.  Don't allocate any resources for it.
+                */
+               if (!i && (tp->tg3_flags3 & TG3_FLG3_ENABLE_RSS))
+                       continue;
+
+               tnapi->rx_rcb = pci_alloc_consistent(tp->pdev,
+                                                    TG3_RX_RCB_RING_BYTES(tp),
+                                                    &tnapi->rx_rcb_mapping);
+               if (!tnapi->rx_rcb)
+                       goto err_out;
+
+               memset(tnapi->rx_rcb, 0, TG3_RX_RCB_RING_BYTES(tp));
+
+               tnapi->tx_buffers = kzalloc(sizeof(struct tx_ring_info) *
+                                           TG3_TX_RING_SIZE, GFP_KERNEL);
+               if (!tnapi->tx_buffers)
+                       goto err_out;
+
+               tnapi->tx_ring = pci_alloc_consistent(tp->pdev,
+                                                     TG3_TX_RING_BYTES,
+                                                     &tnapi->tx_desc_mapping);
+               if (!tnapi->tx_ring)
+                       goto err_out;
+       }
+
        return 0;
 
 err_out:
@@ -5890,7 +6033,6 @@ static int tg3_stop_block(struct tg3 *tp, unsigned long ofs, u32 enable_bit, int
 static int tg3_abort_hw(struct tg3 *tp, int silent)
 {
        int i, err;
-       struct tg3_napi *tnapi = &tp->napi[0];
 
        tg3_disable_ints(tp);
 
@@ -5942,8 +6084,11 @@ static int tg3_abort_hw(struct tg3 *tp, int silent)
        err |= tg3_stop_block(tp, BUFMGR_MODE, BUFMGR_MODE_ENABLE, silent);
        err |= tg3_stop_block(tp, MEMARB_MODE, MEMARB_MODE_ENABLE, silent);
 
-       if (tnapi->hw_status)
-               memset(tnapi->hw_status, 0, TG3_HW_STATUS_SIZE);
+       for (i = 0; i < tp->irq_cnt; i++) {
+               struct tg3_napi *tnapi = &tp->napi[i];
+               if (tnapi->hw_status)
+                       memset(tnapi->hw_status, 0, TG3_HW_STATUS_SIZE);
+       }
        if (tp->hw_stats)
                memset(tp->hw_stats, 0, sizeof(struct tg3_hw_stats));
 
@@ -6230,12 +6375,10 @@ static int tg3_chip_reset(struct tg3 *tp)
 {
        u32 val;
        void (*write_op)(struct tg3 *, u32, u32);
-       int err;
+       int i, err;
 
        tg3_nvram_lock(tp);
 
-       tg3_mdio_stop(tp);
-
        tg3_ape_lock(tp, TG3_APE_LOCK_GRC);
 
        /* No matching tg3_nvram_unlock() after this because
@@ -6270,14 +6413,19 @@ static int tg3_chip_reset(struct tg3 *tp)
         * sharing or irqpoll.
         */
        tp->tg3_flags |= TG3_FLAG_CHIP_RESETTING;
-       if (tp->napi[0].hw_status) {
-               tp->napi[0].hw_status->status = 0;
-               tp->napi[0].hw_status->status_tag = 0;
+       for (i = 0; i < tp->irq_cnt; i++) {
+               struct tg3_napi *tnapi = &tp->napi[i];
+               if (tnapi->hw_status) {
+                       tnapi->hw_status->status = 0;
+                       tnapi->hw_status->status_tag = 0;
+               }
+               tnapi->last_tag = 0;
+               tnapi->last_irq_tag = 0;
        }
-       tp->napi[0].last_tag = 0;
-       tp->napi[0].last_irq_tag = 0;
        smp_mb();
-       synchronize_irq(tp->pdev->irq);
+
+       for (i = 0; i < tp->irq_cnt; i++)
+               synchronize_irq(tp->napi[i].irq_vec);
 
        if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780) {
                val = tr32(TG3_PCIE_LNKCTL) & ~TG3_PCIE_LNKCTL_L1_PLL_PD_EN;
@@ -6433,7 +6581,9 @@ static int tg3_chip_reset(struct tg3 *tp)
        tg3_mdio_start(tp);
 
        if ((tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) &&
-           tp->pci_chip_rev_id != CHIPREV_ID_5750_A0) {
+           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) {
                val = tr32(0x7c00);
 
                tw32(0x7c00, val | (1 << 25));
@@ -6783,24 +6933,175 @@ static void tg3_set_bdinfo(struct tg3 *tp, u32 bdinfo_addr,
 static void __tg3_set_rx_mode(struct net_device *);
 static void __tg3_set_coalesce(struct tg3 *tp, struct ethtool_coalesce *ec)
 {
-       tw32(HOSTCC_RXCOL_TICKS, ec->rx_coalesce_usecs);
-       tw32(HOSTCC_TXCOL_TICKS, ec->tx_coalesce_usecs);
-       tw32(HOSTCC_RXMAX_FRAMES, ec->rx_max_coalesced_frames);
-       tw32(HOSTCC_TXMAX_FRAMES, ec->tx_max_coalesced_frames);
-       if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) {
-               tw32(HOSTCC_RXCOAL_TICK_INT, ec->rx_coalesce_usecs_irq);
-               tw32(HOSTCC_TXCOAL_TICK_INT, ec->tx_coalesce_usecs_irq);
+       int i;
+
+       if (!(tp->tg3_flags2 & TG3_FLG2_USING_MSIX)) {
+               tw32(HOSTCC_TXCOL_TICKS, ec->tx_coalesce_usecs);
+               tw32(HOSTCC_TXMAX_FRAMES, ec->tx_max_coalesced_frames);
+               tw32(HOSTCC_TXCOAL_MAXF_INT, ec->tx_max_coalesced_frames_irq);
+
+               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);
+       } else {
+               tw32(HOSTCC_TXCOL_TICKS, 0);
+               tw32(HOSTCC_TXMAX_FRAMES, 0);
+               tw32(HOSTCC_TXCOAL_MAXF_INT, 0);
+
+               tw32(HOSTCC_RXCOL_TICKS, 0);
+               tw32(HOSTCC_RXMAX_FRAMES, 0);
+               tw32(HOSTCC_RXCOAL_MAXF_INT, 0);
        }
-       tw32(HOSTCC_RXCOAL_MAXF_INT, ec->rx_max_coalesced_frames_irq);
-       tw32(HOSTCC_TXCOAL_MAXF_INT, ec->tx_max_coalesced_frames_irq);
+
        if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) {
                u32 val = ec->stats_block_coalesce_usecs;
 
+               tw32(HOSTCC_RXCOAL_TICK_INT, ec->rx_coalesce_usecs_irq);
+               tw32(HOSTCC_TXCOAL_TICK_INT, ec->tx_coalesce_usecs_irq);
+
                if (!netif_carrier_ok(tp->dev))
                        val = 0;
 
                tw32(HOSTCC_STAT_COAL_TICKS, val);
        }
+
+       for (i = 0; i < tp->irq_cnt - 1; i++) {
+               u32 reg;
+
+               reg = HOSTCC_RXCOL_TICKS_VEC1 + i * 0x18;
+               tw32(reg, ec->rx_coalesce_usecs);
+               reg = HOSTCC_TXCOL_TICKS_VEC1 + i * 0x18;
+               tw32(reg, ec->tx_coalesce_usecs);
+               reg = HOSTCC_RXMAX_FRAMES_VEC1 + i * 0x18;
+               tw32(reg, ec->rx_max_coalesced_frames);
+               reg = HOSTCC_TXMAX_FRAMES_VEC1 + i * 0x18;
+               tw32(reg, ec->tx_max_coalesced_frames);
+               reg = HOSTCC_RXCOAL_MAXF_INT_VEC1 + i * 0x18;
+               tw32(reg, ec->rx_max_coalesced_frames_irq);
+               reg = HOSTCC_TXCOAL_MAXF_INT_VEC1 + i * 0x18;
+               tw32(reg, ec->tx_max_coalesced_frames_irq);
+       }
+
+       for (; i < tp->irq_max - 1; i++) {
+               tw32(HOSTCC_RXCOL_TICKS_VEC1 + i * 0x18, 0);
+               tw32(HOSTCC_TXCOL_TICKS_VEC1 + i * 0x18, 0);
+               tw32(HOSTCC_RXMAX_FRAMES_VEC1 + i * 0x18, 0);
+               tw32(HOSTCC_TXMAX_FRAMES_VEC1 + i * 0x18, 0);
+               tw32(HOSTCC_RXCOAL_MAXF_INT_VEC1 + i * 0x18, 0);
+               tw32(HOSTCC_TXCOAL_MAXF_INT_VEC1 + i * 0x18, 0);
+       }
+}
+
+/* tp->lock is held. */
+static void tg3_rings_reset(struct tg3 *tp)
+{
+       int i;
+       u32 stblk, txrcb, rxrcb, limit;
+       struct tg3_napi *tnapi = &tp->napi[0];
+
+       /* 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
+               limit = NIC_SRAM_SEND_RCB + TG3_BDINFO_SIZE;
+
+       for (txrcb = NIC_SRAM_SEND_RCB + TG3_BDINFO_SIZE;
+            txrcb < limit; txrcb += TG3_BDINFO_SIZE)
+               tg3_write_mem(tp, txrcb + TG3_BDINFO_MAXLEN_FLAGS,
+                             BDINFO_FLAGS_DISABLED);
+
+
+       /* Disable all receive return rings but the first. */
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717)
+               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;
+       else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755)
+               limit = NIC_SRAM_RCV_RET_RCB + TG3_BDINFO_SIZE * 4;
+       else
+               limit = NIC_SRAM_RCV_RET_RCB + TG3_BDINFO_SIZE;
+
+       for (rxrcb = NIC_SRAM_RCV_RET_RCB + TG3_BDINFO_SIZE;
+            rxrcb < limit; rxrcb += TG3_BDINFO_SIZE)
+               tg3_write_mem(tp, rxrcb + TG3_BDINFO_MAXLEN_FLAGS,
+                             BDINFO_FLAGS_DISABLED);
+
+       /* Disable interrupts */
+       tw32_mailbox_f(tp->napi[0].int_mbox, 1);
+
+       /* Zero mailbox registers. */
+       if (tp->tg3_flags & TG3_FLAG_SUPPORT_MSIX) {
+               for (i = 1; i < TG3_IRQ_MAX_VECS; i++) {
+                       tp->napi[i].tx_prod = 0;
+                       tp->napi[i].tx_cons = 0;
+                       tw32_mailbox(tp->napi[i].prodmbox, 0);
+                       tw32_rx_mbox(tp->napi[i].consmbox, 0);
+                       tw32_mailbox_f(tp->napi[i].int_mbox, 1);
+               }
+       } else {
+               tp->napi[0].tx_prod = 0;
+               tp->napi[0].tx_cons = 0;
+               tw32_mailbox(tp->napi[0].prodmbox, 0);
+               tw32_rx_mbox(tp->napi[0].consmbox, 0);
+       }
+
+       /* Make sure the NIC-based send BD rings are disabled. */
+       if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) {
+               u32 mbox = MAILBOX_SNDNIC_PROD_IDX_0 + TG3_64BIT_REG_LOW;
+               for (i = 0; i < 16; i++)
+                       tw32_tx_mbox(mbox + i * 8, 0);
+       }
+
+       txrcb = NIC_SRAM_SEND_RCB;
+       rxrcb = NIC_SRAM_RCV_RET_RCB;
+
+       /* Clear status block in ram. */
+       memset(tnapi->hw_status, 0, TG3_HW_STATUS_SIZE);
+
+       /* Set status block DMA address */
+       tw32(HOSTCC_STATUS_BLK_HOST_ADDR + TG3_64BIT_REG_HIGH,
+            ((u64) tnapi->status_mapping >> 32));
+       tw32(HOSTCC_STATUS_BLK_HOST_ADDR + TG3_64BIT_REG_LOW,
+            ((u64) tnapi->status_mapping & 0xffffffff));
+
+       if (tnapi->tx_ring) {
+               tg3_set_bdinfo(tp, txrcb, tnapi->tx_desc_mapping,
+                              (TG3_TX_RING_SIZE <<
+                               BDINFO_FLAGS_MAXLEN_SHIFT),
+                              NIC_SRAM_TX_BUFFER_DESC);
+               txrcb += TG3_BDINFO_SIZE;
+       }
+
+       if (tnapi->rx_rcb) {
+               tg3_set_bdinfo(tp, rxrcb, tnapi->rx_rcb_mapping,
+                              (TG3_RX_RCB_RING_SIZE(tp) <<
+                               BDINFO_FLAGS_MAXLEN_SHIFT), 0);
+               rxrcb += TG3_BDINFO_SIZE;
+       }
+
+       stblk = HOSTCC_STATBLCK_RING1;
+
+       for (i = 1, tnapi++; i < tp->irq_cnt; i++, tnapi++) {
+               u64 mapping = (u64)tnapi->status_mapping;
+               tw32(stblk + TG3_64BIT_REG_HIGH, mapping >> 32);
+               tw32(stblk + TG3_64BIT_REG_LOW, mapping & 0xffffffff);
+
+               /* Clear status block in ram. */
+               memset(tnapi->hw_status, 0, TG3_HW_STATUS_SIZE);
+
+               tg3_set_bdinfo(tp, txrcb, tnapi->tx_desc_mapping,
+                              (TG3_TX_RING_SIZE <<
+                               BDINFO_FLAGS_MAXLEN_SHIFT),
+                              NIC_SRAM_TX_BUFFER_DESC);
+
+               tg3_set_bdinfo(tp, rxrcb, tnapi->rx_rcb_mapping,
+                              (TG3_RX_RCB_RING_SIZE(tp) <<
+                               BDINFO_FLAGS_MAXLEN_SHIFT), 0);
+
+               stblk += 8;
+               txrcb += TG3_BDINFO_SIZE;
+               rxrcb += TG3_BDINFO_SIZE;
+       }
 }
 
 /* tp->lock is held. */
@@ -6917,7 +7218,8 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
                return err;
 
        if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5784 &&
-           GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5761) {
+           GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5761 &&
+           GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717) {
                /* This value is determined during the probe time DMA
                 * engine test, tg3_test_dma.
                 */
@@ -7071,53 +7373,16 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
                             BDINFO_FLAGS_DISABLED);
                }
 
-               val = RX_STD_MAX_SIZE << BDINFO_FLAGS_MAXLEN_SHIFT;
+               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717)
+                       val = (RX_STD_MAX_SIZE_5705 << BDINFO_FLAGS_MAXLEN_SHIFT) |
+                             (RX_STD_MAX_SIZE << 2);
+               else
+                       val = RX_STD_MAX_SIZE << BDINFO_FLAGS_MAXLEN_SHIFT;
        } else
                val = RX_STD_MAX_SIZE_5705 << BDINFO_FLAGS_MAXLEN_SHIFT;
 
        tw32(RCVDBDI_STD_BD + TG3_BDINFO_MAXLEN_FLAGS, val);
 
-       /* There is only one send ring on 5705/5750, no need to explicitly
-        * disable the others.
-        */
-       if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) {
-               /* Clear out send RCB ring in SRAM. */
-               for (i = NIC_SRAM_SEND_RCB; i < NIC_SRAM_RCV_RET_RCB; i += TG3_BDINFO_SIZE)
-                       tg3_write_mem(tp, i + TG3_BDINFO_MAXLEN_FLAGS,
-                                     BDINFO_FLAGS_DISABLED);
-       }
-
-       tp->tx_prod = 0;
-       tp->tx_cons = 0;
-       tw32_mailbox(MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW, 0);
-       tw32_tx_mbox(MAILBOX_SNDNIC_PROD_IDX_0 + TG3_64BIT_REG_LOW, 0);
-
-       tg3_set_bdinfo(tp, NIC_SRAM_SEND_RCB,
-                      tp->tx_desc_mapping,
-                      (TG3_TX_RING_SIZE <<
-                       BDINFO_FLAGS_MAXLEN_SHIFT),
-                      NIC_SRAM_TX_BUFFER_DESC);
-
-       /* There is only one receive return ring on 5705/5750, no need
-        * to explicitly disable the others.
-        */
-       if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) {
-               for (i = NIC_SRAM_RCV_RET_RCB; i < NIC_SRAM_STATS_BLK;
-                    i += TG3_BDINFO_SIZE) {
-                       tg3_write_mem(tp, i + TG3_BDINFO_MAXLEN_FLAGS,
-                                     BDINFO_FLAGS_DISABLED);
-               }
-       }
-
-       tp->rx_rcb_ptr = 0;
-       tw32_rx_mbox(MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW, 0);
-
-       tg3_set_bdinfo(tp, NIC_SRAM_RCV_RET_RCB,
-                      tp->rx_rcb_mapping,
-                      (TG3_RX_RCB_RING_SIZE(tp) <<
-                       BDINFO_FLAGS_MAXLEN_SHIFT),
-                      0);
-
        tpr->rx_std_ptr = tp->rx_pending;
        tw32_rx_mbox(MAILBOX_RCV_STD_PROD_IDX + TG3_64BIT_REG_LOW,
                     tpr->rx_std_ptr);
@@ -7127,6 +7392,13 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
        tw32_rx_mbox(MAILBOX_RCV_JUMBO_PROD_IDX + TG3_64BIT_REG_LOW,
                     tpr->rx_jmb_ptr);
 
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) {
+               tw32(STD_REPLENISH_LWM, 32);
+               tw32(JMB_REPLENISH_LWM, 16);
+       }
+
+       tg3_rings_reset(tp);
+
        /* Initialize MAC address and backoff seed. */
        __tg3_set_mac_addr(tp, 0);
 
@@ -7214,12 +7486,6 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
 
        __tg3_set_coalesce(tp, &tp->coal);
 
-       /* set status block DMA address */
-       tw32(HOSTCC_STATUS_BLK_HOST_ADDR + TG3_64BIT_REG_HIGH,
-            ((u64) tp->napi[0].status_mapping >> 32));
-       tw32(HOSTCC_STATUS_BLK_HOST_ADDR + TG3_64BIT_REG_LOW,
-            ((u64) tp->napi[0].status_mapping & 0xffffffff));
-
        if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) {
                /* Status/statistics block address.  See tg3_timer,
                 * the tg3_periodic_fetch_stats call there, and
@@ -7230,7 +7496,16 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
                tw32(HOSTCC_STATS_BLK_HOST_ADDR + TG3_64BIT_REG_LOW,
                     ((u64) tp->stats_mapping & 0xffffffff));
                tw32(HOSTCC_STATS_BLK_NIC_ADDR, NIC_SRAM_STATS_BLK);
+
                tw32(HOSTCC_STATUS_BLK_NIC_ADDR, NIC_SRAM_STATUS_BLK);
+
+               /* Clear statistics and status block memory areas */
+               for (i = NIC_SRAM_STATS_BLK;
+                    i < NIC_SRAM_STATUS_BLK + TG3_HW_STATUS_SIZE;
+                    i += sizeof(u32)) {
+                       tg3_write_mem(tp, i, 0);
+                       udelay(40);
+               }
        }
 
        tw32(HOSTCC_MODE, HOSTCC_MODE_ENABLE | tp->coalesce_mode);
@@ -7240,15 +7515,6 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
        if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS))
                tw32(RCVLSC_MODE, RCVLSC_MODE_ENABLE | RCVLSC_MODE_ATTN_ENABLE);
 
-       /* Clear statistics/status block in chip, and status block in ram. */
-       for (i = NIC_SRAM_STATS_BLK;
-            i < NIC_SRAM_STATUS_BLK + TG3_HW_STATUS_SIZE;
-            i += sizeof(u32)) {
-               tg3_write_mem(tp, i, 0);
-               udelay(40);
-       }
-       memset(tp->napi[0].hw_status, 0, TG3_HW_STATUS_SIZE);
-
        if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) {
                tp->tg3_flags2 &= ~TG3_FLG2_PARALLEL_DETECT;
                /* reset to prevent losing 1st rx packet intermittently */
@@ -7300,7 +7566,11 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
        tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl);
        udelay(100);
 
-       tw32_mailbox_f(tp->napi[0].int_mbox, 0);
+       if (tp->tg3_flags2 & TG3_FLG2_USING_MSIX) {
+               val = tr32(MSGINT_MODE);
+               val |= MSGINT_MODE_MULTIVEC_EN | MSGINT_MODE_ENABLE;
+               tw32(MSGINT_MODE, val);
+       }
 
        if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) {
                tw32_f(DMAC_MODE, DMAC_MODE_ENABLE);
@@ -7370,7 +7640,10 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
        tw32(SNDDATAI_MODE, SNDDATAI_MODE_ENABLE);
        if (tp->tg3_flags2 & TG3_FLG2_HW_TSO)
                tw32(SNDDATAI_MODE, SNDDATAI_MODE_ENABLE | 0x8);
-       tw32(SNDBDI_MODE, SNDBDI_MODE_ENABLE | SNDBDI_MODE_ATTN_ENABLE);
+       val = SNDBDI_MODE_ENABLE | SNDBDI_MODE_ATTN_ENABLE;
+       if (tp->tg3_flags2 & TG3_FLG2_USING_MSIX)
+               val |= SNDBDI_MODE_MULTI_TXQ_EN;
+       tw32(SNDBDI_MODE, val);
        tw32(SNDBDS_MODE, SNDBDS_MODE_ENABLE | SNDBDS_MODE_ATTN_ENABLE);
 
        if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0) {
@@ -7389,10 +7662,46 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
        tw32_f(MAC_TX_MODE, tp->tx_mode);
        udelay(100);
 
+       if (tp->tg3_flags3 & TG3_FLG3_ENABLE_RSS) {
+               u32 reg = MAC_RSS_INDIR_TBL_0;
+               u8 *ent = (u8 *)&val;
+
+               /* Setup the indirection table */
+               for (i = 0; i < TG3_RSS_INDIR_TBL_SIZE; i++) {
+                       int idx = i % sizeof(val);
+
+                       ent[idx] = i % (tp->irq_cnt - 1);
+                       if (idx == sizeof(val) - 1) {
+                               tw32(reg, val);
+                               reg += 4;
+                       }
+               }
+
+               /* Setup the "secret" hash key. */
+               tw32(MAC_RSS_HASH_KEY_0, 0x5f865437);
+               tw32(MAC_RSS_HASH_KEY_1, 0xe4ac62cc);
+               tw32(MAC_RSS_HASH_KEY_2, 0x50103a45);
+               tw32(MAC_RSS_HASH_KEY_3, 0x36621985);
+               tw32(MAC_RSS_HASH_KEY_4, 0xbf14c0e8);
+               tw32(MAC_RSS_HASH_KEY_5, 0x1bc27a1e);
+               tw32(MAC_RSS_HASH_KEY_6, 0x84f4b556);
+               tw32(MAC_RSS_HASH_KEY_7, 0x094ea6fe);
+               tw32(MAC_RSS_HASH_KEY_8, 0x7dda01e7);
+               tw32(MAC_RSS_HASH_KEY_9, 0xc04d7481);
+       }
+
        tp->rx_mode = RX_MODE_ENABLE;
        if (tp->tg3_flags3 & TG3_FLG3_5755_PLUS)
                tp->rx_mode |= RX_MODE_IPV6_CSUM_ENABLE;
 
+       if (tp->tg3_flags3 & TG3_FLG3_ENABLE_RSS)
+               tp->rx_mode |= RX_MODE_RSS_ENABLE |
+                              RX_MODE_RSS_ITBL_HASH_BITS_7 |
+                              RX_MODE_RSS_IPV6_HASH_EN |
+                              RX_MODE_RSS_TCP_IPV6_HASH_EN |
+                              RX_MODE_RSS_IPV4_HASH_EN |
+                              RX_MODE_RSS_TCP_IPV4_HASH_EN;
+
        tw32_f(MAC_RX_MODE, tp->rx_mode);
        udelay(10);
 
@@ -7607,7 +7916,7 @@ static void tg3_timer(unsigned long __opaque)
                             tp->grc_local_ctrl | GRC_LCLCTRL_SETINT);
                } else {
                        tw32(HOSTCC_MODE, tp->coalesce_mode |
-                            (HOSTCC_MODE_ENABLE | HOSTCC_MODE_NOW));
+                            HOSTCC_MODE_ENABLE | HOSTCC_MODE_NOW);
                }
 
                if (!(tr32(WDMAC_MODE) & WDMAC_MODE_ENABLE)) {
@@ -7708,13 +8017,22 @@ restart_timer:
        add_timer(&tp->timer);
 }
 
-static int tg3_request_irq(struct tg3 *tp)
+static int tg3_request_irq(struct tg3 *tp, int irq_num)
 {
        irq_handler_t fn;
        unsigned long flags;
-       char *name = tp->dev->name;
+       char *name;
+       struct tg3_napi *tnapi = &tp->napi[irq_num];
 
-       if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) {
+       if (tp->irq_cnt == 1)
+               name = tp->dev->name;
+       else {
+               name = &tnapi->irq_lbl[0];
+               snprintf(name, IFNAMSIZ, "%s-%d", tp->dev->name, irq_num);
+               name[IFNAMSIZ-1] = 0;
+       }
+
+       if (tp->tg3_flags2 & TG3_FLG2_USING_MSI_OR_MSIX) {
                fn = tg3_msi;
                if (tp->tg3_flags2 & TG3_FLG2_1SHOT_MSI)
                        fn = tg3_msi_1shot;
@@ -7725,7 +8043,8 @@ static int tg3_request_irq(struct tg3 *tp)
                        fn = tg3_interrupt_tagged;
                flags = IRQF_SHARED | IRQF_SAMPLE_RANDOM;
        }
-       return request_irq(tp->pdev->irq, fn, flags, name, &tp->napi[0]);
+
+       return request_irq(tnapi->irq_vec, fn, flags, name, tnapi);
 }
 
 static int tg3_test_interrupt(struct tg3 *tp)
@@ -7733,15 +8052,26 @@ static int tg3_test_interrupt(struct tg3 *tp)
        struct tg3_napi *tnapi = &tp->napi[0];
        struct net_device *dev = tp->dev;
        int err, i, intr_ok = 0;
+       u32 val;
 
        if (!netif_running(dev))
                return -ENODEV;
 
        tg3_disable_ints(tp);
 
-       free_irq(tp->pdev->irq, tnapi);
+       free_irq(tnapi->irq_vec, tnapi);
+
+       /*
+        * Turn off MSI one shot mode.  Otherwise this test has no
+        * observable way to know whether the interrupt was delivered.
+        */
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 &&
+           (tp->tg3_flags2 & TG3_FLG2_USING_MSI)) {
+               val = tr32(MSGINT_MODE) | MSGINT_MODE_ONE_SHOT_DISABLE;
+               tw32(MSGINT_MODE, val);
+       }
 
-       err = request_irq(tp->pdev->irq, tg3_test_isr,
+       err = request_irq(tnapi->irq_vec, tg3_test_isr,
                          IRQF_SHARED | IRQF_SAMPLE_RANDOM, dev->name, tnapi);
        if (err)
                return err;
@@ -7750,7 +8080,7 @@ static int tg3_test_interrupt(struct tg3 *tp)
        tg3_enable_ints(tp);
 
        tw32_f(HOSTCC_MODE, tp->coalesce_mode | HOSTCC_MODE_ENABLE |
-              HOSTCC_MODE_NOW);
+              tnapi->coal_now);
 
        for (i = 0; i < 5; i++) {
                u32 int_mbox, misc_host_ctrl;
@@ -7769,15 +8099,22 @@ static int tg3_test_interrupt(struct tg3 *tp)
 
        tg3_disable_ints(tp);
 
-       free_irq(tp->pdev->irq, tnapi);
+       free_irq(tnapi->irq_vec, tnapi);
 
-       err = tg3_request_irq(tp);
+       err = tg3_request_irq(tp, 0);
 
        if (err)
                return err;
 
-       if (intr_ok)
+       if (intr_ok) {
+               /* Reenable MSI one shot mode. */
+               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 &&
+                   (tp->tg3_flags2 & TG3_FLG2_USING_MSI)) {
+                       val = tr32(MSGINT_MODE) & ~MSGINT_MODE_ONE_SHOT_DISABLE;
+                       tw32(MSGINT_MODE, val);
+               }
                return 0;
+       }
 
        return -EIO;
 }
@@ -7817,13 +8154,13 @@ static int tg3_test_msi(struct tg3 *tp)
               "the PCI maintainer and include system chipset information.\n",
                       tp->dev->name);
 
-       free_irq(tp->pdev->irq, &tp->napi[0]);
+       free_irq(tp->napi[0].irq_vec, &tp->napi[0]);
 
        pci_disable_msi(tp->pdev);
 
        tp->tg3_flags2 &= ~TG3_FLG2_USING_MSI;
 
-       err = tg3_request_irq(tp);
+       err = tg3_request_irq(tp, 0);
        if (err)
                return err;
 
@@ -7838,7 +8175,7 @@ static int tg3_test_msi(struct tg3 *tp)
        tg3_full_unlock(tp);
 
        if (err)
-               free_irq(tp->pdev->irq, &tp->napi[0]);
+               free_irq(tp->napi[0].irq_vec, &tp->napi[0]);
 
        return err;
 }
@@ -7874,37 +8211,95 @@ static int tg3_request_firmware(struct tg3 *tp)
        return 0;
 }
 
+static bool tg3_enable_msix(struct tg3 *tp)
+{
+       int i, rc, cpus = num_online_cpus();
+       struct msix_entry msix_ent[tp->irq_max];
+
+       if (cpus == 1)
+               /* Just fallback to the simpler MSI mode. */
+               return false;
+
+       /*
+        * We want as many rx rings enabled as there are cpus.
+        * The first MSIX vector only deals with link interrupts, etc,
+        * so we add one to the number of vectors we are requesting.
+        */
+       tp->irq_cnt = min_t(unsigned, cpus + 1, tp->irq_max);
+
+       for (i = 0; i < tp->irq_max; i++) {
+               msix_ent[i].entry  = i;
+               msix_ent[i].vector = 0;
+       }
+
+       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 (pci_enable_msix(tp->pdev, msix_ent, rc))
+                       return false;
+               printk(KERN_NOTICE
+                      "%s: Requested %d MSI-X vectors, received %d\n",
+                      tp->dev->name, tp->irq_cnt, rc);
+               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;
+
+       tp->dev->real_num_tx_queues = tp->irq_cnt - 1;
+
+       return true;
+}
+
 static void tg3_ints_init(struct tg3 *tp)
 {
-       if (tp->tg3_flags & TG3_FLAG_SUPPORT_MSI) {
+       if ((tp->tg3_flags & TG3_FLAG_SUPPORT_MSI_OR_MSIX) &&
+           !(tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)) {
                /* All MSI supporting chips should support tagged
                 * status.  Assert that this is the case.
                 */
-               if (!(tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)) {
-                       printk(KERN_WARNING PFX "%s: MSI without TAGGED? "
-                              "Not using MSI.\n", tp->dev->name);
-               } else if (pci_enable_msi(tp->pdev) == 0) {
-                       u32 msi_mode;
+               printk(KERN_WARNING PFX "%s: MSI without TAGGED? "
+                      "Not using MSI.\n", tp->dev->name);
+               goto defcfg;
+       }
 
-                       msi_mode = tr32(MSGINT_MODE);
-                       tw32(MSGINT_MODE, msi_mode | MSGINT_MODE_ENABLE);
-                       tp->tg3_flags2 |= TG3_FLG2_USING_MSI;
-               }
+       if ((tp->tg3_flags & TG3_FLAG_SUPPORT_MSIX) && tg3_enable_msix(tp))
+               tp->tg3_flags2 |= TG3_FLG2_USING_MSIX;
+       else if ((tp->tg3_flags & TG3_FLAG_SUPPORT_MSI) &&
+                pci_enable_msi(tp->pdev) == 0)
+               tp->tg3_flags2 |= TG3_FLG2_USING_MSI;
+
+       if (tp->tg3_flags2 & TG3_FLG2_USING_MSI_OR_MSIX) {
+               u32 msi_mode = tr32(MSGINT_MODE);
+               if (tp->tg3_flags2 & TG3_FLG2_USING_MSIX)
+                       msi_mode |= MSGINT_MODE_MULTIVEC_EN;
+               tw32(MSGINT_MODE, msi_mode | MSGINT_MODE_ENABLE);
+       }
+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;
        }
 }
 
 static void tg3_ints_fini(struct tg3 *tp)
 {
-               if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) {
-                       pci_disable_msi(tp->pdev);
-                       tp->tg3_flags2 &= ~TG3_FLG2_USING_MSI;
-               }
+       if (tp->tg3_flags2 & TG3_FLG2_USING_MSIX)
+               pci_disable_msix(tp->pdev);
+       else if (tp->tg3_flags2 & TG3_FLG2_USING_MSI)
+               pci_disable_msi(tp->pdev);
+       tp->tg3_flags2 &= ~TG3_FLG2_USING_MSI_OR_MSIX;
+       tp->tg3_flags3 &= ~TG3_FLG3_ENABLE_RSS;
 }
 
 static int tg3_open(struct net_device *dev)
 {
        struct tg3 *tp = netdev_priv(dev);
-       int err;
+       int i, err;
 
        if (tp->fw_needed) {
                err = tg3_request_firmware(tp);
@@ -7935,21 +8330,33 @@ static int tg3_open(struct net_device *dev)
 
        tg3_full_unlock(tp);
 
+       /*
+        * Setup interrupts first so we know how
+        * many NAPI resources to allocate
+        */
+       tg3_ints_init(tp);
+
        /* The placement of this call is tied
         * to the setup and use of Host TX descriptors.
         */
        err = tg3_alloc_consistent(tp);
        if (err)
-               return err;
-
-       tg3_ints_init(tp);
+               goto err_out1;
 
-       napi_enable(&tp->napi[0].napi);
+       tg3_napi_enable(tp);
 
-       err = tg3_request_irq(tp);
+       for (i = 0; i < tp->irq_cnt; i++) {
+               struct tg3_napi *tnapi = &tp->napi[i];
+               err = tg3_request_irq(tp, i);
+               if (err) {
+                       for (i--; i >= 0; i--)
+                               free_irq(tnapi->irq_vec, tnapi);
+                       break;
+               }
+       }
 
        if (err)
-               goto err_out1;
+               goto err_out2;
 
        tg3_full_lock(tp, 0);
 
@@ -7978,7 +8385,7 @@ static int tg3_open(struct net_device *dev)
        tg3_full_unlock(tp);
 
        if (err)
-               goto err_out2;
+               goto err_out3;
 
        if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) {
                err = tg3_test_msi(tp);
@@ -7989,16 +8396,16 @@ static int tg3_open(struct net_device *dev)
                        tg3_free_rings(tp);
                        tg3_full_unlock(tp);
 
-                       goto err_out1;
+                       goto err_out2;
                }
 
-               if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) {
-                       if (tp->tg3_flags2 & TG3_FLG2_1SHOT_MSI) {
-                               u32 val = tr32(PCIE_TRANSACTION_CFG);
+               if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717 &&
+                   (tp->tg3_flags2 & TG3_FLG2_USING_MSI) &&
+                   (tp->tg3_flags2 & TG3_FLG2_1SHOT_MSI)) {
+                       u32 val = tr32(PCIE_TRANSACTION_CFG);
 
-                               tw32(PCIE_TRANSACTION_CFG,
-                                    val | PCIE_TRANS_CFG_1SHOT_MSI);
-                       }
+                       tw32(PCIE_TRANSACTION_CFG,
+                            val | PCIE_TRANS_CFG_1SHOT_MSI);
                }
        }
 
@@ -8012,17 +8419,22 @@ static int tg3_open(struct net_device *dev)
 
        tg3_full_unlock(tp);
 
-       netif_start_queue(dev);
+       netif_tx_start_all_queues(dev);
 
        return 0;
 
+err_out3:
+       for (i = tp->irq_cnt - 1; i >= 0; i--) {
+               struct tg3_napi *tnapi = &tp->napi[i];
+               free_irq(tnapi->irq_vec, tnapi);
+       }
+
 err_out2:
-       free_irq(tp->pdev->irq, &tp->napi[0]);
+       tg3_napi_disable(tp);
+       tg3_free_consistent(tp);
 
 err_out1:
-       napi_disable(&tp->napi[0].napi);
        tg3_ints_fini(tp);
-       tg3_free_consistent(tp);
        return err;
 }
 
@@ -8261,15 +8673,18 @@ static struct tg3_ethtool_stats *tg3_get_estats(struct tg3 *);
 
 static int tg3_close(struct net_device *dev)
 {
+       int i;
        struct tg3 *tp = netdev_priv(dev);
 
-       napi_disable(&tp->napi[0].napi);
+       tg3_napi_disable(tp);
        cancel_work_sync(&tp->reset_task);
 
-       netif_stop_queue(dev);
+       netif_tx_stop_all_queues(dev);
 
        del_timer_sync(&tp->timer);
 
+       tg3_phy_stop(tp);
+
        tg3_full_lock(tp, 1);
 #if 0
        tg3_dump_state(tp);
@@ -8283,7 +8698,10 @@ static int tg3_close(struct net_device *dev)
 
        tg3_full_unlock(tp);
 
-       free_irq(tp->pdev->irq, &tp->napi[0]);
+       for (i = tp->irq_cnt - 1; i >= 0; i--) {
+               struct tg3_napi *tnapi = &tp->napi[i];
+               free_irq(tnapi->irq_vec, tnapi);
+       }
 
        tg3_ints_fini(tp);
 
@@ -8850,7 +9268,7 @@ static int tg3_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
                cmd->speed = tp->link_config.active_speed;
                cmd->duplex = tp->link_config.active_duplex;
        }
-       cmd->phy_address = PHY_ADDR;
+       cmd->phy_address = tp->phy_addr;
        cmd->transceiver = XCVR_INTERNAL;
        cmd->autoneg = tp->link_config.autoneg;
        cmd->maxtxpkt = 0;
@@ -9025,7 +9443,8 @@ static int tg3_set_tso(struct net_device *dev, u32 value)
                            (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 ||
+                           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717)
                                dev->features |= NETIF_F_TSO_ECN;
                } else
                        dev->features &= ~(NETIF_F_TSO6 | NETIF_F_TSO_ECN);
@@ -9087,13 +9506,13 @@ static void tg3_get_ringparam(struct net_device *dev, struct ethtool_ringparam *
        else
                ering->rx_jumbo_pending = 0;
 
-       ering->tx_pending = tp->tx_pending;
+       ering->tx_pending = tp->napi[0].tx_pending;
 }
 
 static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ering)
 {
        struct tg3 *tp = netdev_priv(dev);
-       int irq_sync = 0, err = 0;
+       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) ||
@@ -9117,7 +9536,9 @@ static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *e
            tp->rx_pending > 63)
                tp->rx_pending = 63;
        tp->rx_jumbo_pending = ering->rx_jumbo_pending;
-       tp->tx_pending = ering->tx_pending;
+
+       for (i = 0; i < TG3_IRQ_MAX_VECS; i++)
+               tp->napi[i].tx_pending = ering->tx_pending;
 
        if (netif_running(dev)) {
                tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
@@ -9825,7 +10246,7 @@ static int tg3_test_memory(struct tg3 *tp)
 static int tg3_run_loopback(struct tg3 *tp, int loopback_mode)
 {
        u32 mac_mode, rx_start_idx, rx_idx, tx_idx, opaque_key;
-       u32 desc_idx;
+       u32 desc_idx, coal_now;
        struct sk_buff *skb, *rx_skb;
        u8 *tx_data;
        dma_addr_t map;
@@ -9834,8 +10255,14 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode)
        struct tg3_napi *tnapi, *rnapi;
        struct tg3_rx_prodring_set *tpr = &tp->prodring[0];
 
-       tnapi = &tp->napi[0];
-       rnapi = &tp->napi[0];
+       if (tp->irq_cnt > 1) {
+               tnapi = &tp->napi[1];
+               rnapi = &tp->napi[1];
+       } else {
+               tnapi = &tp->napi[0];
+               rnapi = &tp->napi[0];
+       }
+       coal_now = tnapi->coal_now | rnapi->coal_now;
 
        if (loopback_mode == TG3_MAC_LOOPBACK) {
                /* HW errata - mac loopback fails in some cases on 5780.
@@ -9914,7 +10341,7 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode)
        map = pci_map_single(tp->pdev, skb->data, tx_len, PCI_DMA_TODEVICE);
 
        tw32_f(HOSTCC_MODE, tp->coalesce_mode | HOSTCC_MODE_ENABLE |
-            HOSTCC_MODE_NOW);
+              rnapi->coal_now);
 
        udelay(10);
 
@@ -9922,27 +10349,26 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode)
 
        num_pkts = 0;
 
-       tg3_set_txd(tp, tp->tx_prod, map, tx_len, 0, 1);
+       tg3_set_txd(tnapi, tnapi->tx_prod, map, tx_len, 0, 1);
 
-       tp->tx_prod++;
+       tnapi->tx_prod++;
        num_pkts++;
 
-       tw32_tx_mbox(MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW,
-                    tp->tx_prod);
-       tr32_mailbox(MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW);
+       tw32_tx_mbox(tnapi->prodmbox, tnapi->tx_prod);
+       tr32_mailbox(tnapi->prodmbox);
 
        udelay(10);
 
        /* 250 usec to allow enough time on some 10/100 Mbps devices.  */
        for (i = 0; i < 25; i++) {
                tw32_f(HOSTCC_MODE, tp->coalesce_mode | HOSTCC_MODE_ENABLE |
-                      HOSTCC_MODE_NOW);
+                      coal_now);
 
                udelay(10);
 
                tx_idx = tnapi->hw_status->idx[0].tx_consumer;
                rx_idx = rnapi->hw_status->idx[0].rx_producer;
-               if ((tx_idx == tp->tx_prod) &&
+               if ((tx_idx == tnapi->tx_prod) &&
                    (rx_idx == (rx_start_idx + num_pkts)))
                        break;
        }
@@ -9950,13 +10376,13 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode)
        pci_unmap_single(tp->pdev, map, tx_len, PCI_DMA_TODEVICE);
        dev_kfree_skb(skb);
 
-       if (tx_idx != tp->tx_prod)
+       if (tx_idx != tnapi->tx_prod)
                goto out;
 
        if (rx_idx != rx_start_idx + num_pkts)
                goto out;
 
-       desc = &tp->rx_rcb[rx_start_idx];
+       desc = &rnapi->rx_rcb[rx_start_idx];
        desc_idx = desc->opaque & RXD_OPAQUE_INDEX_MASK;
        opaque_key = desc->opaque & RXD_OPAQUE_RING_MASK;
        if (opaque_key != RXD_OPAQUE_RING_STD)
@@ -10146,7 +10572,7 @@ static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 
        switch(cmd) {
        case SIOCGMIIPHY:
-               data->phy_id = PHY_ADDR;
+               data->phy_id = tp->phy_addr;
 
                /* fallthru */
        case SIOCGMIIREG: {
@@ -10171,9 +10597,6 @@ static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
                if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)
                        break;                  /* We have no PHY */
 
-               if (!capable(CAP_NET_ADMIN))
-                       return -EPERM;
-
                if (tp->link_config.phy_is_low_power)
                        return -EAGAIN;
 
@@ -10429,6 +10852,33 @@ static void __devinit tg3_get_nvram_info(struct tg3 *tp)
        }
 }
 
+static void __devinit tg3_nvram_get_pagesize(struct tg3 *tp, u32 nvmcfg1)
+{
+       switch (nvmcfg1 & NVRAM_CFG1_5752PAGE_SIZE_MASK) {
+       case FLASH_5752PAGE_SIZE_256:
+               tp->nvram_pagesize = 256;
+               break;
+       case FLASH_5752PAGE_SIZE_512:
+               tp->nvram_pagesize = 512;
+               break;
+       case FLASH_5752PAGE_SIZE_1K:
+               tp->nvram_pagesize = 1024;
+               break;
+       case FLASH_5752PAGE_SIZE_2K:
+               tp->nvram_pagesize = 2048;
+               break;
+       case FLASH_5752PAGE_SIZE_4K:
+               tp->nvram_pagesize = 4096;
+               break;
+       case FLASH_5752PAGE_SIZE_264:
+               tp->nvram_pagesize = 264;
+               break;
+       case FLASH_5752PAGE_SIZE_528:
+               tp->nvram_pagesize = 528;
+               break;
+       }
+}
+
 static void __devinit tg3_get_5752_nvram_info(struct tg3 *tp)
 {
        u32 nvcfg1;
@@ -10460,26 +10910,7 @@ static void __devinit tg3_get_5752_nvram_info(struct tg3 *tp)
        }
 
        if (tp->tg3_flags2 & TG3_FLG2_FLASH) {
-               switch (nvcfg1 & NVRAM_CFG1_5752PAGE_SIZE_MASK) {
-               case FLASH_5752PAGE_SIZE_256:
-                       tp->nvram_pagesize = 256;
-                       break;
-               case FLASH_5752PAGE_SIZE_512:
-                       tp->nvram_pagesize = 512;
-                       break;
-               case FLASH_5752PAGE_SIZE_1K:
-                       tp->nvram_pagesize = 1024;
-                       break;
-               case FLASH_5752PAGE_SIZE_2K:
-                       tp->nvram_pagesize = 2048;
-                       break;
-               case FLASH_5752PAGE_SIZE_4K:
-                       tp->nvram_pagesize = 4096;
-                       break;
-               case FLASH_5752PAGE_SIZE_264:
-                       tp->nvram_pagesize = 264;
-                       break;
-               }
+               tg3_nvram_get_pagesize(tp, nvcfg1);
        } else {
                /* For eeprom, set pagesize to maximum eeprom size */
                tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE;
@@ -10732,34 +11163,84 @@ static void __devinit tg3_get_57780_nvram_info(struct tg3 *tp)
                return;
        }
 
-       switch (nvcfg1 & NVRAM_CFG1_5752PAGE_SIZE_MASK) {
-       case FLASH_5752PAGE_SIZE_256:
-               tp->tg3_flags3 |= TG3_FLG3_NO_NVRAM_ADDR_TRANS;
-               tp->nvram_pagesize = 256;
-               break;
-       case FLASH_5752PAGE_SIZE_512:
-               tp->tg3_flags3 |= TG3_FLG3_NO_NVRAM_ADDR_TRANS;
-               tp->nvram_pagesize = 512;
-               break;
-       case FLASH_5752PAGE_SIZE_1K:
-               tp->tg3_flags3 |= TG3_FLG3_NO_NVRAM_ADDR_TRANS;
-               tp->nvram_pagesize = 1024;
-               break;
-       case FLASH_5752PAGE_SIZE_2K:
+       tg3_nvram_get_pagesize(tp, nvcfg1);
+       if (tp->nvram_pagesize != 264 && tp->nvram_pagesize != 528)
                tp->tg3_flags3 |= TG3_FLG3_NO_NVRAM_ADDR_TRANS;
-               tp->nvram_pagesize = 2048;
-               break;
-       case FLASH_5752PAGE_SIZE_4K:
-               tp->tg3_flags3 |= TG3_FLG3_NO_NVRAM_ADDR_TRANS;
-               tp->nvram_pagesize = 4096;
-               break;
-       case FLASH_5752PAGE_SIZE_264:
-               tp->nvram_pagesize = 264;
+}
+
+
+static void __devinit tg3_get_5717_nvram_info(struct tg3 *tp)
+{
+       u32 nvcfg1;
+
+       nvcfg1 = tr32(NVRAM_CFG1);
+
+       switch (nvcfg1 & NVRAM_CFG1_5752VENDOR_MASK) {
+       case FLASH_5717VENDOR_ATMEL_EEPROM:
+       case FLASH_5717VENDOR_MICRO_EEPROM:
+               tp->nvram_jedecnum = JEDEC_ATMEL;
+               tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
+               tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE;
+
+               nvcfg1 &= ~NVRAM_CFG1_COMPAT_BYPASS;
+               tw32(NVRAM_CFG1, nvcfg1);
+               return;
+       case FLASH_5717VENDOR_ATMEL_MDB011D:
+       case FLASH_5717VENDOR_ATMEL_ADB011B:
+       case FLASH_5717VENDOR_ATMEL_ADB011D:
+       case FLASH_5717VENDOR_ATMEL_MDB021D:
+       case FLASH_5717VENDOR_ATMEL_ADB021B:
+       case FLASH_5717VENDOR_ATMEL_ADB021D:
+       case FLASH_5717VENDOR_ATMEL_45USPT:
+               tp->nvram_jedecnum = JEDEC_ATMEL;
+               tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
+               tp->tg3_flags2 |= TG3_FLG2_FLASH;
+
+               switch (nvcfg1 & NVRAM_CFG1_5752VENDOR_MASK) {
+               case FLASH_5717VENDOR_ATMEL_MDB021D:
+               case FLASH_5717VENDOR_ATMEL_ADB021B:
+               case FLASH_5717VENDOR_ATMEL_ADB021D:
+                       tp->nvram_size = TG3_NVRAM_SIZE_256KB;
+                       break;
+               default:
+                       tp->nvram_size = TG3_NVRAM_SIZE_128KB;
+                       break;
+               }
                break;
-       case FLASH_5752PAGE_SIZE_528:
-               tp->nvram_pagesize = 528;
+       case FLASH_5717VENDOR_ST_M_M25PE10:
+       case FLASH_5717VENDOR_ST_A_M25PE10:
+       case FLASH_5717VENDOR_ST_M_M45PE10:
+       case FLASH_5717VENDOR_ST_A_M45PE10:
+       case FLASH_5717VENDOR_ST_M_M25PE20:
+       case FLASH_5717VENDOR_ST_A_M25PE20:
+       case FLASH_5717VENDOR_ST_M_M45PE20:
+       case FLASH_5717VENDOR_ST_A_M45PE20:
+       case FLASH_5717VENDOR_ST_25USPT:
+       case FLASH_5717VENDOR_ST_45USPT:
+               tp->nvram_jedecnum = JEDEC_ST;
+               tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
+               tp->tg3_flags2 |= TG3_FLG2_FLASH;
+
+               switch (nvcfg1 & NVRAM_CFG1_5752VENDOR_MASK) {
+               case FLASH_5717VENDOR_ST_M_M25PE20:
+               case FLASH_5717VENDOR_ST_A_M25PE20:
+               case FLASH_5717VENDOR_ST_M_M45PE20:
+               case FLASH_5717VENDOR_ST_A_M45PE20:
+                       tp->nvram_size = TG3_NVRAM_SIZE_256KB;
+                       break;
+               default:
+                       tp->nvram_size = TG3_NVRAM_SIZE_128KB;
+                       break;
+               }
                break;
+       default:
+               tp->tg3_flags3 |= TG3_FLG3_NO_NVRAM;
+               return;
        }
+
+       tg3_nvram_get_pagesize(tp, nvcfg1);
+       if (tp->nvram_pagesize != 264 && tp->nvram_pagesize != 528)
+               tp->tg3_flags3 |= TG3_FLG3_NO_NVRAM_ADDR_TRANS;
 }
 
 /* Chips other than 5700/5701 use the NVRAM for fetching info. */
@@ -10804,6 +11285,8 @@ static void __devinit tg3_nvram_init(struct tg3 *tp)
                        tg3_get_5906_nvram_info(tp);
                else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780)
                        tg3_get_57780_nvram_info(tp);
+               else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717)
+                       tg3_get_5717_nvram_info(tp);
                else
                        tg3_get_nvram_info(tp);
 
@@ -11917,8 +12400,17 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
        if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_USE_PROD_ID_REG) {
                u32 prod_id_asic_rev;
 
-               pci_read_config_dword(tp->pdev, TG3PCI_PRODID_ASICREV,
-                                     &prod_id_asic_rev);
+               if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717C ||
+                   tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717S ||
+                   tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718C ||
+                   tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718S)
+                       pci_read_config_dword(tp->pdev,
+                                             TG3PCI_GEN2_PRODID_ASICREV,
+                                             &prod_id_asic_rev);
+               else
+                       pci_read_config_dword(tp->pdev, TG3PCI_PRODID_ASICREV,
+                                             &prod_id_asic_rev);
+
                tp->pci_chip_rev_id = prod_id_asic_rev;
        }
 
@@ -12056,8 +12548,9 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
        pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
                               tp->misc_host_ctrl);
 
-       if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) ||
-           (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714))
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717)
                tp->pdev_peer = tg3_find_peer(tp);
 
        /* Intentionally exclude ASIC_REV_5906 */
@@ -12066,7 +12559,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
            GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
            GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
            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 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717)
                tp->tg3_flags3 |= TG3_FLG3_5755_PLUS;
 
        if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 ||
@@ -12114,8 +12608,18 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
                }
        }
 
+       tp->irq_max = 1;
+
+#ifdef TG3_NAPI
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) {
+               tp->tg3_flags |= TG3_FLAG_SUPPORT_MSIX;
+               tp->irq_max = TG3_IRQ_MAX_VECS;
+       }
+#endif
+
        if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) ||
-            (tp->tg3_flags2 & TG3_FLG2_5780_CLASS))
+            (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717)
                tp->tg3_flags |= TG3_FLAG_JUMBO_CAPABLE;
 
        pci_read_config_dword(tp->pdev, TG3PCI_PCISTATE,
@@ -12249,7 +12753,6 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
                tp->write32 = tg3_write_flush_reg32;
        }
 
-
        if ((tp->tg3_flags & TG3_FLAG_TXD_MBOX_HWBUG) ||
            (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)) {
                tp->write32_tx_mbox = tg3_write32_tx_mbox;
@@ -12308,7 +12811,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
        if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
            GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
            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 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717)
                tp->tg3_flags |= TG3_FLAG_CPMU_PRESENT;
 
        /* Set up tp->grc_local_ctrl before calling tg3_set_power_state().
@@ -12386,7 +12890,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
        if ((tp->tg3_flags2 & TG3_FLG2_5705_PLUS) &&
            !(tp->tg3_flags3 & TG3_FLG3_PHY_IS_FET) &&
            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 &&
+           GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717) {
                if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
                    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
                    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
@@ -12628,8 +13133,10 @@ static int __devinit tg3_get_device_address(struct tg3 *tp)
                        tw32_f(NVRAM_CMD, NVRAM_CMD_RESET);
                else
                        tg3_nvram_unlock(tp);
-       }
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
+       } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) {
+               if (tr32(TG3_CPMU_STATUS) & TG3_CPMU_STATUS_PCIE_FUNC)
+                       mac_offset = 0xcc;
+       } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
                mac_offset = 0x10;
 
        /* First try to get it from MAC address mailbox. */
@@ -13110,7 +13617,8 @@ static void __devinit tg3_init_link_config(struct tg3 *tp)
 
 static void __devinit tg3_init_bufmgr_config(struct tg3 *tp)
 {
-       if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) {
+       if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS &&
+           GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717) {
                tp->bufmgr_config.mbuf_read_dma_low_water =
                        DEFAULT_MB_RDMA_LOW_WATER_5705;
                tp->bufmgr_config.mbuf_mac_rx_low_water =
@@ -13315,7 +13823,8 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
        static int tg3_version_printed = 0;
        struct net_device *dev;
        struct tg3 *tp;
-       int err, pm_cap;
+       int i, err, pm_cap;
+       u32 sndmbx, rcvmbx, intmbx;
        char str[40];
        u64 dma_mask, persist_dma_mask;
 
@@ -13347,7 +13856,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
                goto err_out_free_res;
        }
 
-       dev = alloc_etherdev(sizeof(*tp));
+       dev = alloc_etherdev_mq(sizeof(*tp), TG3_IRQ_MAX_VECS);
        if (!dev) {
                printk(KERN_ERR PFX "Etherdev alloc failed, aborting.\n");
                err = -ENOMEM;
@@ -13409,10 +13918,51 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
 
        tp->rx_pending = TG3_DEF_RX_RING_PENDING;
        tp->rx_jumbo_pending = TG3_DEF_RX_JUMBO_RING_PENDING;
-       tp->tx_pending = TG3_DEF_TX_RING_PENDING;
 
-       tp->napi[0].tp = tp;
-       tp->napi[0].int_mbox = MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW;
+       intmbx = MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW;
+       rcvmbx = MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW;
+       sndmbx = MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW;
+       for (i = 0; i < TG3_IRQ_MAX_VECS; i++) {
+               struct tg3_napi *tnapi = &tp->napi[i];
+
+               tnapi->tp = tp;
+               tnapi->tx_pending = TG3_DEF_TX_RING_PENDING;
+
+               tnapi->int_mbox = intmbx;
+               if (i < 4)
+                       intmbx += 0x8;
+               else
+                       intmbx += 0x4;
+
+               tnapi->consmbox = rcvmbx;
+               tnapi->prodmbox = sndmbx;
+
+               if (i)
+                       tnapi->coal_now = HOSTCC_MODE_COAL_VEC1_NOW << (i - 1);
+               else
+                       tnapi->coal_now = HOSTCC_MODE_NOW;
+
+               if (!(tp->tg3_flags & TG3_FLAG_SUPPORT_MSIX))
+                       break;
+
+               /*
+                * If we support MSIX, we'll be using RSS.  If we're using
+                * RSS, the first vector only handles link interrupts and the
+                * remaining vectors handle rx and tx interrupts.  Reuse the
+                * mailbox values for the next iteration.  The values we setup
+                * above are still useful for the single vectored mode.
+                */
+               if (!i)
+                       continue;
+
+               rcvmbx += 0x8;
+
+               if (sndmbx & 0x4)
+                       sndmbx -= 0x4;
+               else
+                       sndmbx += 0xc;
+       }
+
        netif_napi_add(dev, &tp->napi[0].napi, tg3_poll, 64);
        dev->ethtool_ops = &tg3_ethtool_ops;
        dev->watchdog_timeo = TG3_TX_TIMEOUT;
@@ -13507,7 +14057,8 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
                    (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 ||
+                   GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717)
                        dev->features |= NETIF_F_TSO_ECN;
        }