]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - drivers/net/tg3.c
[PATCH] tg3: add 5714/5715 support
[net-next-2.6.git] / drivers / net / tg3.c
index af8263a1580ea5b6fca000c5ea59b2cd3af7a4af..cf2204f5b7f9da2be7e2b4c296221b8efd23a4fc 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/ip.h>
 #include <linux/tcp.h>
 #include <linux/workqueue.h>
+#include <linux/prefetch.h>
 
 #include <net/checksum.h>
 
@@ -66,8 +67,8 @@
 
 #define DRV_MODULE_NAME                "tg3"
 #define PFX DRV_MODULE_NAME    ": "
-#define DRV_MODULE_VERSION     "3.37"
-#define DRV_MODULE_RELDATE     "August 25, 2005"
+#define DRV_MODULE_VERSION     "3.42"
+#define DRV_MODULE_RELDATE     "Oct 3, 2005"
 
 #define TG3_DEF_MAC_MODE       0
 #define TG3_DEF_RX_MODE                0
                                   TG3_RX_RCB_RING_SIZE(tp))
 #define TG3_TX_RING_BYTES      (sizeof(struct tg3_tx_buffer_desc) * \
                                 TG3_TX_RING_SIZE)
-#define TX_RING_GAP(TP)        \
-       (TG3_TX_RING_SIZE - (TP)->tx_pending)
 #define TX_BUFFS_AVAIL(TP)                                             \
-       (((TP)->tx_cons <= (TP)->tx_prod) ?                             \
-         (TP)->tx_cons + (TP)->tx_pending - (TP)->tx_prod :            \
-         (TP)->tx_cons - (TP)->tx_prod - TX_RING_GAP(TP))
+       ((TP)->tx_pending -                                             \
+        (((TP)->tx_prod - (TP)->tx_cons) & (TG3_TX_RING_SIZE - 1)))
 #define NEXT_TX(N)             (((N) + 1) & (TG3_TX_RING_SIZE - 1))
 
 #define RX_PKT_BUF_SZ          (1536 + tp->rx_offset + 64)
@@ -221,6 +219,10 @@ static struct pci_device_id tg3_pci_tbl[] = {
          PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
        { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753F,
          PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5714,
+         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+       { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5715,
+         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
        { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5780,
          PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
        { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5780S,
@@ -490,7 +492,8 @@ static void tg3_disable_ints(struct tg3 *tp)
 
 static inline void tg3_cond_int(struct tg3 *tp)
 {
-       if (tp->hw_status->status & SD_STATUS_UPDATED)
+       if (!(tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) &&
+           (tp->hw_status->status & SD_STATUS_UPDATED))
                tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl | GRC_LCLCTRL_SETINT);
 }
 
@@ -571,7 +574,7 @@ static void tg3_switch_clocks(struct tg3 *tp)
        u32 clock_ctrl = tr32(TG3PCI_CLOCK_CTRL);
        u32 orig_clock_ctrl;
 
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780)
+       if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)
                return;
 
        orig_clock_ctrl = clock_ctrl;
@@ -1211,7 +1214,7 @@ static int tg3_set_power_state(struct tg3 *tp, int state)
                     CLOCK_CTRL_ALTCLK |
                     CLOCK_CTRL_PWRDOWN_PLL133);
                udelay(40);
-       } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780) {
+       } else if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) {
                /* do nothing */
        } else if (!((tp->tg3_flags2 & TG3_FLG2_5750_PLUS) &&
                     (tp->tg3_flags & TG3_FLAG_ENABLE_ASF))) {
@@ -2880,9 +2883,13 @@ static void tg3_tx(struct tg3 *tp)
 
        tp->tx_cons = sw_idx;
 
-       if (netif_queue_stopped(tp->dev) &&
-           (TX_BUFFS_AVAIL(tp) > TG3_TX_WAKEUP_THRESH))
-               netif_wake_queue(tp->dev);
+       if (unlikely(netif_queue_stopped(tp->dev))) {
+               spin_lock(&tp->tx_lock);
+               if (netif_queue_stopped(tp->dev) &&
+                   (TX_BUFFS_AVAIL(tp) > TG3_TX_WAKEUP_THRESH))
+                       netif_wake_queue(tp->dev);
+               spin_unlock(&tp->tx_lock);
+       }
 }
 
 /* Returns size of skb allocated or < 0 on error.
@@ -3198,9 +3205,7 @@ static int tg3_poll(struct net_device *netdev, int *budget)
 
        /* run TX completion thread */
        if (sblk->idx[0].tx_consumer != tp->tx_cons) {
-               spin_lock(&tp->tx_lock);
                tg3_tx(tp);
-               spin_unlock(&tp->tx_lock);
        }
 
        /* run RX thread, within the bounds set by NAPI.
@@ -3220,18 +3225,17 @@ static int tg3_poll(struct net_device *netdev, int *budget)
                netdev->quota -= work_done;
        }
 
-       if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)
+       if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) {
                tp->last_tag = sblk->status_tag;
-       rmb();
-       sblk->status &= ~SD_STATUS_UPDATED;
+               rmb();
+       } else
+               sblk->status &= ~SD_STATUS_UPDATED;
 
        /* if no more work, tell net stack and NIC we're done */
        done = !tg3_has_work(tp);
        if (done) {
-               spin_lock(&tp->lock);
                netif_rx_complete(netdev);
                tg3_restart_ints(tp);
-               spin_unlock(&tp->lock);
        }
 
        return (done ? 0 : 1);
@@ -3279,8 +3283,9 @@ static irqreturn_t tg3_msi(int irq, void *dev_id, struct pt_regs *regs)
 {
        struct net_device *dev = dev_id;
        struct tg3 *tp = netdev_priv(dev);
-       struct tg3_hw_status *sblk = tp->hw_status;
 
+       prefetch(tp->hw_status);
+       prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]);
        /*
         * Writing any value to intr-mbox-0 clears PCI INTA# and
         * chip-internal interrupt pending events.
@@ -3289,19 +3294,9 @@ static irqreturn_t tg3_msi(int irq, void *dev_id, struct pt_regs *regs)
         * event coalescing.
         */
        tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001);
-       tp->last_tag = sblk->status_tag;
-       rmb();
-       if (tg3_irq_sync(tp))
-               goto out;
-       sblk->status &= ~SD_STATUS_UPDATED;
-       if (likely(tg3_has_work(tp)))
+       if (likely(!tg3_irq_sync(tp)))
                netif_rx_schedule(dev);         /* schedule NAPI poll */
-       else {
-               /* No work, re-enable interrupts.  */
-               tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
-                            tp->last_tag << 24);
-       }
-out:
+
        return IRQ_RETVAL(1);
 }
 
@@ -3331,9 +3326,10 @@ static irqreturn_t tg3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                if (tg3_irq_sync(tp))
                        goto out;
                sblk->status &= ~SD_STATUS_UPDATED;
-               if (likely(tg3_has_work(tp)))
+               if (likely(tg3_has_work(tp))) {
+                       prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]);
                        netif_rx_schedule(dev);         /* schedule NAPI poll */
-               else {
+               else {
                        /* No work, shared interrupt perhaps?  re-enable
                         * interrupts, and flush that PCI write
                         */
@@ -3359,7 +3355,7 @@ static irqreturn_t tg3_interrupt_tagged(int irq, void *dev_id, struct pt_regs *r
         * Reading the PCI State register will confirm whether the
         * interrupt is ours and will flush the status block.
         */
-       if ((sblk->status & SD_STATUS_UPDATED) ||
+       if ((sblk->status_tag != tp->last_tag) ||
            !(tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) {
                /*
                 * writing any value to intr-mbox-0 clears PCI INTA# and
@@ -3370,19 +3366,17 @@ static irqreturn_t tg3_interrupt_tagged(int irq, void *dev_id, struct pt_regs *r
                 */
                tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
                             0x00000001);
-               tp->last_tag = sblk->status_tag;
-               rmb();
                if (tg3_irq_sync(tp))
                        goto out;
-               sblk->status &= ~SD_STATUS_UPDATED;
-               if (likely(tg3_has_work(tp)))
-                       netif_rx_schedule(dev);         /* schedule NAPI poll */
-               else {
-                       /* no work, shared interrupt perhaps?  re-enable
-                        * interrupts, and flush that PCI write
+               if (netif_rx_schedule_prep(dev)) {
+                       prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]);
+                       /* Update last_tag to mark that this status has been
+                        * seen. Because interrupt may be shared, we may be
+                        * racing with tg3_poll(), so only update last_tag
+                        * if tg3_poll() is not scheduled.
                         */
-                       tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
-                                      tp->last_tag << 24);
+                       tp->last_tag = sblk->status_tag;
+                       __netif_rx_schedule(dev);
                }
        } else {        /* shared interrupt */
                handled = 0;
@@ -3399,7 +3393,8 @@ static irqreturn_t tg3_test_isr(int irq, void *dev_id,
        struct tg3 *tp = netdev_priv(dev);
        struct tg3_hw_status *sblk = tp->hw_status;
 
-       if (sblk->status & SD_STATUS_UPDATED) {
+       if ((sblk->status & SD_STATUS_UPDATED) ||
+           !(tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) {
                tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
                             0x00000001);
                return IRQ_RETVAL(1);
@@ -3452,31 +3447,47 @@ static void tg3_tx_timeout(struct net_device *dev)
        schedule_work(&tp->reset_task);
 }
 
+/* Test for DMA buffers crossing any 4GB boundaries: 4G, 8G, etc */
+static inline int tg3_4g_overflow_test(dma_addr_t mapping, int len)
+{
+       u32 base = (u32) mapping & 0xffffffff;
+
+       return ((base > 0xffffdcc0) &&
+               (base + len + 8 < base));
+}
+
 static void tg3_set_txd(struct tg3 *, int, dma_addr_t, int, u32, u32);
 
 static int tigon3_4gb_hwbug_workaround(struct tg3 *tp, struct sk_buff *skb,
-                                      u32 guilty_entry, int guilty_len,
-                                      u32 last_plus_one, u32 *start, u32 mss)
+                                      u32 last_plus_one, u32 *start,
+                                      u32 base_flags, u32 mss)
 {
        struct sk_buff *new_skb = skb_copy(skb, GFP_ATOMIC);
-       dma_addr_t new_addr;
+       dma_addr_t new_addr = 0;
        u32 entry = *start;
-       int i;
+       int i, ret = 0;
 
        if (!new_skb) {
-               dev_kfree_skb(skb);
-               return -1;
+               ret = -1;
+       } else {
+               /* New SKB is guaranteed to be linear. */
+               entry = *start;
+               new_addr = pci_map_single(tp->pdev, new_skb->data, new_skb->len,
+                                         PCI_DMA_TODEVICE);
+               /* Make sure new skb does not cross any 4G boundaries.
+                * Drop the packet if it does.
+                */
+               if (tg3_4g_overflow_test(new_addr, new_skb->len)) {
+                       ret = -1;
+                       dev_kfree_skb(new_skb);
+                       new_skb = NULL;
+               } else {
+                       tg3_set_txd(tp, entry, new_addr, new_skb->len,
+                                   base_flags, 1 | (mss << 1));
+                       *start = NEXT_TX(entry);
+               }
        }
 
-       /* New SKB is guaranteed to be linear. */
-       entry = *start;
-       new_addr = pci_map_single(tp->pdev, new_skb->data, new_skb->len,
-                                 PCI_DMA_TODEVICE);
-       tg3_set_txd(tp, entry, new_addr, new_skb->len,
-                   (skb->ip_summed == CHECKSUM_HW) ?
-                   TXD_FLAG_TCPUDP_CSUM : 0, 1 | (mss << 1));
-       *start = NEXT_TX(entry);
-
        /* Now clean up the sw ring entries. */
        i = 0;
        while (entry != last_plus_one) {
@@ -3501,7 +3512,7 @@ static int tigon3_4gb_hwbug_workaround(struct tg3 *tp, struct sk_buff *skb,
 
        dev_kfree_skb(skb);
 
-       return 0;
+       return ret;
 }
 
 static void tg3_set_txd(struct tg3 *tp, int entry,
@@ -3527,19 +3538,10 @@ static void tg3_set_txd(struct tg3 *tp, int entry,
        txd->vlan_tag = vlan_tag << TXD_VLAN_TAG_SHIFT;
 }
 
-static inline int tg3_4g_overflow_test(dma_addr_t mapping, int len)
-{
-       u32 base = (u32) mapping & 0xffffffff;
-
-       return ((base > 0xffffdcc0) &&
-               (base + len + 8 < base));
-}
-
 static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct tg3 *tp = netdev_priv(dev);
        dma_addr_t mapping;
-       unsigned int i;
        u32 len, entry, base_flags, mss;
        int would_hit_hwbug;
 
@@ -3634,7 +3636,7 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
        would_hit_hwbug = 0;
 
        if (tg3_4g_overflow_test(mapping, len))
-               would_hit_hwbug = entry + 1;
+               would_hit_hwbug = 1;
 
        tg3_set_txd(tp, entry, mapping, len, base_flags,
                    (skb_shinfo(skb)->nr_frags == 0) | (mss << 1));
@@ -3658,12 +3660,8 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
                        tp->tx_buffers[entry].skb = NULL;
                        pci_unmap_addr_set(&tp->tx_buffers[entry], mapping, mapping);
 
-                       if (tg3_4g_overflow_test(mapping, len)) {
-                               /* Only one should match. */
-                               if (would_hit_hwbug)
-                                       BUG();
-                               would_hit_hwbug = entry + 1;
-                       }
+                       if (tg3_4g_overflow_test(mapping, len))
+                               would_hit_hwbug = 1;
 
                        if (tp->tg3_flags2 & TG3_FLG2_HW_TSO)
                                tg3_set_txd(tp, entry, mapping, len,
@@ -3679,34 +3677,15 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
        if (would_hit_hwbug) {
                u32 last_plus_one = entry;
                u32 start;
-               unsigned int len = 0;
-
-               would_hit_hwbug -= 1;
-               entry = entry - 1 - skb_shinfo(skb)->nr_frags;
-               entry &= (TG3_TX_RING_SIZE - 1);
-               start = entry;
-               i = 0;
-               while (entry != last_plus_one) {
-                       if (i == 0)
-                               len = skb_headlen(skb);
-                       else
-                               len = skb_shinfo(skb)->frags[i-1].size;
-
-                       if (entry == would_hit_hwbug)
-                               break;
-
-                       i++;
-                       entry = NEXT_TX(entry);
 
-               }
+               start = entry - 1 - skb_shinfo(skb)->nr_frags;
+               start &= (TG3_TX_RING_SIZE - 1);
 
                /* If the workaround fails due to memory/mapping
                 * failure, silently drop this packet.
                 */
-               if (tigon3_4gb_hwbug_workaround(tp, skb,
-                                               entry, len,
-                                               last_plus_one,
-                                               &start, mss))
+               if (tigon3_4gb_hwbug_workaround(tp, skb, last_plus_one,
+                                               &start, base_flags, mss))
                        goto out_unlock;
 
                entry = start;
@@ -3716,8 +3695,11 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
        tw32_tx_mbox((MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW), entry);
 
        tp->tx_prod = entry;
-       if (TX_BUFFS_AVAIL(tp) <= (MAX_SKB_FRAGS + 1))
+       if (TX_BUFFS_AVAIL(tp) <= (MAX_SKB_FRAGS + 1)) {
                netif_stop_queue(dev);
+               if (TX_BUFFS_AVAIL(tp) > TG3_TX_WAKEUP_THRESH)
+                       netif_wake_queue(tp->dev);
+       }
 
 out_unlock:
        mmiowb();
@@ -3734,14 +3716,14 @@ static inline void tg3_set_mtu(struct net_device *dev, struct tg3 *tp,
        dev->mtu = new_mtu;
 
        if (new_mtu > ETH_DATA_LEN) {
-               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780) {
+               if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) {
                        tp->tg3_flags2 &= ~TG3_FLG2_TSO_CAPABLE;
                        ethtool_op_set_tso(dev, 0);
                }
                else
                        tp->tg3_flags |= TG3_FLAG_JUMBO_RING_ENABLE;
        } else {
-               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780)
+               if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)
                        tp->tg3_flags2 |= TG3_FLG2_TSO_CAPABLE;
                tp->tg3_flags &= ~TG3_FLAG_JUMBO_RING_ENABLE;
        }
@@ -3872,7 +3854,7 @@ static void tg3_init_rings(struct tg3 *tp)
        memset(tp->tx_ring, 0, TG3_TX_RING_BYTES);
 
        tp->rx_pkt_buf_sz = RX_PKT_BUF_SZ;
-       if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780) &&
+       if ((tp->tg3_flags2 & TG3_FLG2_5780_CLASS) &&
            (tp->dev->mtu > ETH_DATA_LEN))
                tp->rx_pkt_buf_sz = RX_JUMBO_PKT_BUF_SZ;
 
@@ -4369,7 +4351,7 @@ static int tg3_chip_reset(struct tg3 *tp)
        val &= ~PCIX_CAPS_RELAXED_ORDERING;
        pci_write_config_dword(tp->pdev, TG3PCI_X_CAPS, val);
 
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780) {
+       if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) {
                u32 val;
 
                /* Chip reset on 5780 will reset MSI enable bit,
@@ -5418,6 +5400,9 @@ static int tg3_set_mac_addr(struct net_device *dev, void *p)
        struct tg3 *tp = netdev_priv(dev);
        struct sockaddr *addr = p;
 
+       if (!is_valid_ether_addr(addr->sa_data))
+               return -EINVAL;
+
        memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
 
        spin_lock_bh(&tp->lock);
@@ -5829,6 +5814,13 @@ static int tg3_reset_hw(struct tg3 *tp)
        }
        memset(tp->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 */
+               tw32_f(MAC_RX_MODE, RX_MODE_RESET);
+               udelay(10);
+       }
+
        tp->mac_mode = MAC_MODE_TXSTAT_ENABLE | MAC_MODE_RXSTAT_ENABLE |
                MAC_MODE_TDE_ENABLE | MAC_MODE_RDE_ENABLE | MAC_MODE_FHDE_ENABLE;
        tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_RXSTAT_CLEAR | MAC_MODE_TXSTAT_CLEAR);
@@ -6015,7 +6007,7 @@ static int tg3_reset_hw(struct tg3 *tp)
        tw32(MAC_RCV_VALUE_1, 0xffffffff & RCV_RULE_DISABLE_MASK);
 
        if ((tp->tg3_flags2 & TG3_FLG2_5705_PLUS) &&
-           (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5780))
+           !(tp->tg3_flags2 & TG3_FLG2_5780_CLASS))
                limit = 8;
        else
                limit = 16;
@@ -6242,6 +6234,7 @@ static int tg3_test_interrupt(struct tg3 *tp)
        if (err)
                return err;
 
+       tp->hw_status->status &= ~SD_STATUS_UPDATED;
        tg3_enable_ints(tp);
 
        tw32_f(HOSTCC_MODE, tp->coalesce_mode | HOSTCC_MODE_ENABLE |
@@ -6899,8 +6892,7 @@ static struct net_device_stats *tg3_get_stats(struct net_device *dev)
                get_stat64(&hw_stats->tx_octets);
 
        stats->rx_errors = old_stats->rx_errors +
-               get_stat64(&hw_stats->rx_errors) +
-               get_stat64(&hw_stats->rx_discards);
+               get_stat64(&hw_stats->rx_errors);
        stats->tx_errors = old_stats->tx_errors +
                get_stat64(&hw_stats->tx_errors) +
                get_stat64(&hw_stats->tx_mac_errors) +
@@ -6928,6 +6920,9 @@ static struct net_device_stats *tg3_get_stats(struct net_device *dev)
        stats->rx_crc_errors = old_stats->rx_crc_errors +
                calc_crc_errors(tp);
 
+       stats->rx_missed_errors = old_stats->rx_missed_errors +
+               get_stat64(&hw_stats->rx_discards);
+
        return stats;
 }
 
@@ -7246,7 +7241,7 @@ static int tg3_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
                cmd->supported |= (SUPPORTED_1000baseT_Half |
                                   SUPPORTED_1000baseT_Full);
 
-       if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES))
+       if (!(tp->tg3_flags2 & TG3_FLG2_ANY_SERDES))
                cmd->supported |= (SUPPORTED_100baseT_Half |
                                  SUPPORTED_100baseT_Full |
                                  SUPPORTED_10baseT_Half |
@@ -7380,12 +7375,17 @@ static int tg3_nway_reset(struct net_device *dev)
        if (!netif_running(dev))
                return -EAGAIN;
 
+       if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)
+               return -EINVAL;
+
        spin_lock_bh(&tp->lock);
        r = -EINVAL;
        tg3_readphy(tp, MII_BMCR, &bmcr);
        if (!tg3_readphy(tp, MII_BMCR, &bmcr) &&
-           (bmcr & BMCR_ANENABLE)) {
-               tg3_writephy(tp, MII_BMCR, bmcr | BMCR_ANRESTART);
+           ((bmcr & BMCR_ANENABLE) ||
+            (tp->tg3_flags2 & TG3_FLG2_PARALLEL_DETECT))) {
+               tg3_writephy(tp, MII_BMCR, bmcr | BMCR_ANRESTART |
+                                          BMCR_ANENABLE);
                r = 0;
        }
        spin_unlock_bh(&tp->lock);
@@ -7557,6 +7557,38 @@ static void tg3_get_strings (struct net_device *dev, u32 stringset, u8 *buf)
        }
 }
 
+static int tg3_phys_id(struct net_device *dev, u32 data)
+{
+       struct tg3 *tp = netdev_priv(dev);
+       int i;
+
+       if (!netif_running(tp->dev))
+               return -EAGAIN;
+
+       if (data == 0)
+               data = 2;
+
+       for (i = 0; i < (data * 2); i++) {
+               if ((i % 2) == 0)
+                       tw32(MAC_LED_CTRL, LED_CTRL_LNKLED_OVERRIDE |
+                                          LED_CTRL_1000MBPS_ON |
+                                          LED_CTRL_100MBPS_ON |
+                                          LED_CTRL_10MBPS_ON |
+                                          LED_CTRL_TRAFFIC_OVERRIDE |
+                                          LED_CTRL_TRAFFIC_BLINK |
+                                          LED_CTRL_TRAFFIC_LED);
+       
+               else
+                       tw32(MAC_LED_CTRL, LED_CTRL_LNKLED_OVERRIDE |
+                                          LED_CTRL_TRAFFIC_OVERRIDE);
+
+               if (msleep_interruptible(500))
+                       break;
+       }
+       tw32(MAC_LED_CTRL, tp->led_ctrl);
+       return 0;
+}
+
 static void tg3_get_ethtool_stats (struct net_device *dev,
                                   struct ethtool_stats *estats, u64 *tmp_stats)
 {
@@ -7616,7 +7648,7 @@ static int tg3_test_link(struct tg3 *tp)
        if (!netif_running(tp->dev))
                return -ENODEV;
 
-       if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)
+       if (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES)
                max = TG3_SERDES_TIMEOUT_SEC;
        else
                max = TG3_COPPER_TIMEOUT_SEC;
@@ -7901,9 +7933,12 @@ static int tg3_test_memory(struct tg3 *tp)
        return err;
 }
 
-static int tg3_test_loopback(struct tg3 *tp)
+#define TG3_MAC_LOOPBACK       0
+#define TG3_PHY_LOOPBACK       1
+
+static int tg3_run_loopback(struct tg3 *tp, int loopback_mode)
 {
-       u32 mac_mode, send_idx, rx_start_idx, rx_idx, tx_idx, opaque_key;
+       u32 mac_mode, rx_start_idx, rx_idx, tx_idx, opaque_key;
        u32 desc_idx;
        struct sk_buff *skb, *rx_skb;
        u8 *tx_data;
@@ -7911,17 +7946,38 @@ static int tg3_test_loopback(struct tg3 *tp)
        int num_pkts, tx_len, rx_len, i, err;
        struct tg3_rx_buffer_desc *desc;
 
-       if (!netif_running(tp->dev))
-               return -ENODEV;
-
-       err = -EIO;
+       if (loopback_mode == TG3_MAC_LOOPBACK) {
+               /* HW errata - mac loopback fails in some cases on 5780.
+                * Normal traffic and PHY loopback are not affected by
+                * errata.
+                */
+               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780)
+                       return 0;
 
-       tg3_reset_hw(tp);
+               mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) |
+                          MAC_MODE_PORT_INT_LPBACK | MAC_MODE_LINK_POLARITY |
+                          MAC_MODE_PORT_MODE_GMII;
+               tw32(MAC_MODE, mac_mode);
+       } else if (loopback_mode == TG3_PHY_LOOPBACK) {
+               tg3_writephy(tp, MII_BMCR, BMCR_LOOPBACK | BMCR_FULLDPLX |
+                                          BMCR_SPEED1000);
+               udelay(40);
+               /* reset to prevent losing 1st rx packet intermittently */
+               if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) {
+                       tw32_f(MAC_RX_MODE, RX_MODE_RESET);
+                       udelay(10);
+                       tw32_f(MAC_RX_MODE, tp->rx_mode);
+               }
+               mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) |
+                          MAC_MODE_LINK_POLARITY | MAC_MODE_PORT_MODE_GMII;
+               if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401)
+                       mac_mode &= ~MAC_MODE_LINK_POLARITY;
+               tw32(MAC_MODE, mac_mode);
+       }
+       else
+               return -EINVAL;
 
-       mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) |
-                  MAC_MODE_PORT_INT_LPBACK | MAC_MODE_LINK_POLARITY |
-                  MAC_MODE_PORT_MODE_GMII;
-       tw32(MAC_MODE, mac_mode);
+       err = -EIO;
 
        tx_len = 1514;
        skb = dev_alloc_skb(tx_len);
@@ -7943,15 +7999,15 @@ static int tg3_test_loopback(struct tg3 *tp)
 
        rx_start_idx = tp->hw_status->idx[0].rx_producer;
 
-       send_idx = 0;
        num_pkts = 0;
 
-       tg3_set_txd(tp, send_idx, map, tx_len, 0, 1);
+       tg3_set_txd(tp, tp->tx_prod, map, tx_len, 0, 1);
 
-       send_idx++;
+       tp->tx_prod++;
        num_pkts++;
 
-       tw32_tx_mbox(MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW, send_idx);
+       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);
 
        udelay(10);
@@ -7964,7 +8020,7 @@ static int tg3_test_loopback(struct tg3 *tp)
 
                tx_idx = tp->hw_status->idx[0].tx_consumer;
                rx_idx = tp->hw_status->idx[0].rx_producer;
-               if ((tx_idx == send_idx) &&
+               if ((tx_idx == tp->tx_prod) &&
                    (rx_idx == (rx_start_idx + num_pkts)))
                        break;
        }
@@ -7972,7 +8028,7 @@ static int tg3_test_loopback(struct tg3 *tp)
        pci_unmap_single(tp->pdev, map, tx_len, PCI_DMA_TODEVICE);
        dev_kfree_skb(skb);
 
-       if (tx_idx != send_idx)
+       if (tx_idx != tp->tx_prod)
                goto out;
 
        if (rx_idx != rx_start_idx + num_pkts)
@@ -8008,6 +8064,30 @@ out:
        return err;
 }
 
+#define TG3_MAC_LOOPBACK_FAILED                1
+#define TG3_PHY_LOOPBACK_FAILED                2
+#define TG3_LOOPBACK_FAILED            (TG3_MAC_LOOPBACK_FAILED |      \
+                                        TG3_PHY_LOOPBACK_FAILED)
+
+static int tg3_test_loopback(struct tg3 *tp)
+{
+       int err = 0;
+
+       if (!netif_running(tp->dev))
+               return TG3_LOOPBACK_FAILED;
+
+       tg3_reset_hw(tp);
+
+       if (tg3_run_loopback(tp, TG3_MAC_LOOPBACK))
+               err |= TG3_MAC_LOOPBACK_FAILED;
+       if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) {
+               if (tg3_run_loopback(tp, TG3_PHY_LOOPBACK))
+                       err |= TG3_PHY_LOOPBACK_FAILED;
+       }
+
+       return err;
+}
+
 static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest,
                          u64 *data)
 {
@@ -8048,10 +8128,8 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest,
                        etest->flags |= ETH_TEST_FL_FAILED;
                        data[3] = 1;
                }
-               if (tg3_test_loopback(tp) != 0) {
+               if ((data[4] = tg3_test_loopback(tp)) != 0)
                        etest->flags |= ETH_TEST_FL_FAILED;
-                       data[4] = 1;
-               }
 
                tg3_full_unlock(tp);
 
@@ -8239,10 +8317,12 @@ static struct ethtool_ops tg3_ethtool_ops = {
        .self_test_count        = tg3_get_test_count,
        .self_test              = tg3_self_test,
        .get_strings            = tg3_get_strings,
+       .phys_id                = tg3_phys_id,
        .get_stats_count        = tg3_get_stats_count,
        .get_ethtool_stats      = tg3_get_ethtool_stats,
        .get_coalesce           = tg3_get_coalesce,
        .set_coalesce           = tg3_set_coalesce,
+       .get_perm_addr          = ethtool_op_get_perm_addr,
 };
 
 static void __devinit tg3_get_eeprom_size(struct tg3 *tp)
@@ -8303,7 +8383,8 @@ static void __devinit tg3_get_nvram_info(struct tg3 *tp)
                tw32(NVRAM_CFG1, nvcfg1);
        }
 
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
+       if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) ||
+           (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) {
                switch (nvcfg1 & NVRAM_CFG1_VENDOR_MASK) {
                        case FLASH_VENDOR_ATMEL_FLASH_BUFFERED:
                                tp->nvram_jedecnum = JEDEC_ATMEL;
@@ -8717,8 +8798,9 @@ static int tg3_nvram_write_block_buffered(struct tg3 *tp, u32 offset, u32 len,
                if (i == (len - 4))
                        nvram_cmd |= NVRAM_CMD_LAST;
 
-               if ((tp->nvram_jedecnum == JEDEC_ST) &&
-                       (nvram_cmd & NVRAM_CMD_FIRST)) {
+               if ((GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5752) &&
+                   (tp->nvram_jedecnum == JEDEC_ST) &&
+                   (nvram_cmd & NVRAM_CMD_FIRST)) {
 
                        if ((ret = tg3_nvram_exec_cmd(tp,
                                NVRAM_CMD_WREN | NVRAM_CMD_GO |
@@ -8902,7 +8984,7 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
 
                tp->phy_id = eeprom_phy_id;
                if (eeprom_phy_serdes) {
-                       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780)
+                       if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)
                                tp->tg3_flags2 |= TG3_FLG2_MII_SERDES;
                        else
                                tp->tg3_flags2 |= TG3_FLG2_PHY_SERDES;
@@ -9206,6 +9288,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
        static struct pci_device_id write_reorder_chipsets[] = {
                { PCI_DEVICE(PCI_VENDOR_ID_AMD,
                             PCI_DEVICE_ID_AMD_FE_GATE_700C) },
+               { PCI_DEVICE(PCI_VENDOR_ID_VIA,
+                            PCI_DEVICE_ID_VIA_8385_0) },
                { },
        };
        u32 misc_ctrl_reg;
@@ -9220,15 +9304,6 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
                tp->tg3_flags2 |= TG3_FLG2_SUN_570X;
 #endif
 
-       /* If we have an AMD 762 chipset, write
-        * reordering to the mailbox registers done by the host
-        * controller can cause major troubles.  We read back from
-        * every mailbox register write to force the writes to be
-        * posted to the chip in order.
-        */
-       if (pci_dev_present(write_reorder_chipsets))
-               tp->tg3_flags |= TG3_FLAG_MBOX_WRITE_REORDER;
-
        /* Force memory write invalidate off.  If we leave it on,
         * then on 5700_BX chips we have to enable a workaround.
         * The workaround is to set the TG3PCI_DMA_RW_CTRL boundary
@@ -9322,8 +9397,11 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
        }
 
        /* Find msi capability. */
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780)
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714) {
+               tp->tg3_flags2 |= TG3_FLG2_5780_CLASS;
                tp->msi_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_MSI);
+       }
 
        /* Initialize misc host control in PCI block. */
        tp->misc_host_ctrl |= (misc_ctrl_reg &
@@ -9341,7 +9419,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
 
        if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 ||
            GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 ||
-           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780)
+           (tp->tg3_flags2 & TG3_FLG2_5780_CLASS))
                tp->tg3_flags2 |= TG3_FLG2_5750_PLUS;
 
        if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) ||
@@ -9359,6 +9437,16 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
        if (pci_find_capability(tp->pdev, PCI_CAP_ID_EXP) != 0)
                tp->tg3_flags2 |= TG3_FLG2_PCI_EXPRESS;
 
+       /* If we have an AMD 762 or VIA K8T800 chipset, write
+        * reordering to the mailbox registers done by the host
+        * controller can cause major troubles.  We read back from
+        * every mailbox register write to force the writes to be
+        * posted to the chip in order.
+        */
+       if (pci_dev_present(write_reorder_chipsets) &&
+           !(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS))
+               tp->tg3_flags |= TG3_FLAG_MBOX_WRITE_REORDER;
+
        if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 &&
            tp->pci_lat_timer < 64) {
                tp->pci_lat_timer = 64;
@@ -9467,7 +9555,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
                tp->write32_rx_mbox = tg3_write_indirect_mbox;
 
                iounmap(tp->regs);
-               tp->regs = 0;
+               tp->regs = NULL;
 
                pci_read_config_word(tp->pdev, PCI_COMMAND, &pci_cmd);
                pci_cmd &= ~PCI_COMMAND_MEMORY;
@@ -9526,7 +9614,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
         * ether_setup() via the alloc_etherdev() call
         */
        if (tp->dev->mtu > ETH_DATA_LEN &&
-           GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5780)
+           !(tp->tg3_flags2 & TG3_FLG2_5780_CLASS))
                tp->tg3_flags |= TG3_FLAG_JUMBO_RING_ENABLE;
 
        /* Determine WakeOnLan speed to use. */
@@ -9719,6 +9807,7 @@ static int __devinit tg3_get_macaddr_sparc(struct tg3 *tp)
                if (prom_getproplen(node, "local-mac-address") == 6) {
                        prom_getproperty(node, "local-mac-address",
                                         dev->dev_addr, 6);
+                       memcpy(dev->perm_addr, dev->dev_addr, 6);
                        return 0;
                }
        }
@@ -9730,6 +9819,7 @@ static int __devinit tg3_get_default_macaddr_sparc(struct tg3 *tp)
        struct net_device *dev = tp->dev;
 
        memcpy(dev->dev_addr, idprom->id_ethaddr, 6);
+       memcpy(dev->perm_addr, idprom->id_ethaddr, 6);
        return 0;
 }
 #endif
@@ -9747,7 +9837,7 @@ static int __devinit tg3_get_device_address(struct tg3 *tp)
        mac_offset = 0x7c;
        if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 &&
             !(tp->tg3_flags & TG3_FLG2_SUN_570X)) ||
-           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780) {
+           (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) {
                if (tr32(TG3PCI_DUAL_MAC_CTRL) & DUAL_MAC_CTRL_ID)
                        mac_offset = 0xcc;
                if (tg3_nvram_lock(tp))
@@ -9799,6 +9889,7 @@ static int __devinit tg3_get_device_address(struct tg3 *tp)
 #endif
                return -EINVAL;
        }
+       memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
        return 0;
 }
 
@@ -10064,6 +10155,9 @@ static int __devinit tg3_test_dma(struct tg3 *tp)
                } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780) {
                        /* 5780 always in PCIX mode */
                        tp->dma_rwctrl |= 0x00144000;
+               } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714) {
+                       /* 5714 always in PCIX mode */
+                       tp->dma_rwctrl |= 0x00148000;
                } else {
                        tp->dma_rwctrl |= 0x001b000f;
                }
@@ -10263,6 +10357,7 @@ static char * __devinit tg3_phy_string(struct tg3 *tp)
        case PHY_ID_BCM5705:    return "5705";
        case PHY_ID_BCM5750:    return "5750";
        case PHY_ID_BCM5752:    return "5752";
+       case PHY_ID_BCM5714:    return "5714";
        case PHY_ID_BCM5780:    return "5780";
        case PHY_ID_BCM8002:    return "8002/serdes";
        case 0:                 return "serdes";
@@ -10270,6 +10365,44 @@ static char * __devinit tg3_phy_string(struct tg3 *tp)
        };
 }
 
+static char * __devinit tg3_bus_string(struct tg3 *tp, char *str)
+{
+       if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) {
+               strcpy(str, "PCI Express");
+               return str;
+       } else if (tp->tg3_flags & TG3_FLAG_PCIX_MODE) {
+               u32 clock_ctrl = tr32(TG3PCI_CLOCK_CTRL) & 0x1f;
+
+               strcpy(str, "PCIX:");
+
+               if ((clock_ctrl == 7) ||
+                   ((tr32(GRC_MISC_CFG) & GRC_MISC_CFG_BOARD_ID_MASK) ==
+                    GRC_MISC_CFG_BOARD_ID_5704CIOBE))
+                       strcat(str, "133MHz");
+               else if (clock_ctrl == 0)
+                       strcat(str, "33MHz");
+               else if (clock_ctrl == 2)
+                       strcat(str, "50MHz");
+               else if (clock_ctrl == 4)
+                       strcat(str, "66MHz");
+               else if (clock_ctrl == 6)
+                       strcat(str, "100MHz");
+               else if (clock_ctrl == 7)
+                       strcat(str, "133MHz");
+       } else {
+               strcpy(str, "PCI:");
+               if (tp->tg3_flags & TG3_FLAG_PCI_HIGH_SPEED)
+                       strcat(str, "66MHz");
+               else
+                       strcat(str, "33MHz");
+       }
+       if (tp->tg3_flags & TG3_FLAG_PCI_32BIT)
+               strcat(str, ":32-bit");
+       else
+               strcat(str, ":64-bit");
+       return str;
+}
+
 static struct pci_dev * __devinit tg3_find_5704_peer(struct tg3 *tp)
 {
        struct pci_dev *peer;
@@ -10332,6 +10465,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
        struct net_device *dev;
        struct tg3 *tp;
        int i, err, pci_using_dac, pm_cap;
+       char str[40];
 
        if (tg3_version_printed++ == 0)
                printk(KERN_INFO "%s", version);
@@ -10577,16 +10711,12 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
 
        pci_set_drvdata(pdev, dev);
 
-       printk(KERN_INFO "%s: Tigon3 [partno(%s) rev %04x PHY(%s)] (PCI%s:%s:%s) %sBaseT Ethernet ",
+       printk(KERN_INFO "%s: Tigon3 [partno(%s) rev %04x PHY(%s)] (%s) %sBaseT Ethernet ",
               dev->name,
               tp->board_part_number,
               tp->pci_chip_rev_id,
               tg3_phy_string(tp),
-              ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) ? "X" : ""),
-              ((tp->tg3_flags & TG3_FLAG_PCI_HIGH_SPEED) ?
-               ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) ? "133MHz" : "66MHz") :
-               ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) ? "100MHz" : "33MHz")),
-              ((tp->tg3_flags & TG3_FLAG_PCI_32BIT) ? "32-bit" : "64-bit"),
+              tg3_bus_string(tp, str),
               (tp->tg3_flags & TG3_FLAG_10_100_ONLY) ? "10/100" : "10/100/1000");
 
        for (i = 0; i < 6; i++)
@@ -10612,7 +10742,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
 err_out_iounmap:
        if (tp->regs) {
                iounmap(tp->regs);
-               tp->regs = 0;
+               tp->regs = NULL;
        }
 
 err_out_free_dev:
@@ -10637,7 +10767,7 @@ static void __devexit tg3_remove_one(struct pci_dev *pdev)
                unregister_netdev(dev);
                if (tp->regs) {
                        iounmap(tp->regs);
-                       tp->regs = 0;
+                       tp->regs = NULL;
                }
                free_netdev(dev);
                pci_release_regions(pdev);