aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/tg3.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/tg3.c')
-rw-r--r--drivers/net/tg3.c73
1 files changed, 53 insertions, 20 deletions
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 3bddfd705838..a174e616eda5 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -7935,9 +7935,12 @@ static int tg3_test_memory(struct tg3 *tp)
7935 return err; 7935 return err;
7936} 7936}
7937 7937
7938static int tg3_test_loopback(struct tg3 *tp) 7938#define TG3_MAC_LOOPBACK 0
7939#define TG3_PHY_LOOPBACK 1
7940
7941static int tg3_run_loopback(struct tg3 *tp, int loopback_mode)
7939{ 7942{
7940 u32 mac_mode, send_idx, rx_start_idx, rx_idx, tx_idx, opaque_key; 7943 u32 mac_mode, rx_start_idx, rx_idx, tx_idx, opaque_key;
7941 u32 desc_idx; 7944 u32 desc_idx;
7942 struct sk_buff *skb, *rx_skb; 7945 struct sk_buff *skb, *rx_skb;
7943 u8 *tx_data; 7946 u8 *tx_data;
@@ -7945,18 +7948,26 @@ static int tg3_test_loopback(struct tg3 *tp)
7945 int num_pkts, tx_len, rx_len, i, err; 7948 int num_pkts, tx_len, rx_len, i, err;
7946 struct tg3_rx_buffer_desc *desc; 7949 struct tg3_rx_buffer_desc *desc;
7947 7950
7948 if (!netif_running(tp->dev)) 7951 if (loopback_mode == TG3_MAC_LOOPBACK) {
7949 return -ENODEV; 7952 mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) |
7953 MAC_MODE_PORT_INT_LPBACK | MAC_MODE_LINK_POLARITY |
7954 MAC_MODE_PORT_MODE_GMII;
7955 tw32(MAC_MODE, mac_mode);
7956 } else if (loopback_mode == TG3_PHY_LOOPBACK) {
7957 mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) |
7958 MAC_MODE_LINK_POLARITY | MAC_MODE_PORT_MODE_GMII;
7959 if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401)
7960 mac_mode &= ~MAC_MODE_LINK_POLARITY;
7961 tw32(MAC_MODE, mac_mode);
7962
7963 tg3_writephy(tp, MII_BMCR, BMCR_LOOPBACK | BMCR_FULLDPLX |
7964 BMCR_SPEED1000);
7965 }
7966 else
7967 return -EINVAL;
7950 7968
7951 err = -EIO; 7969 err = -EIO;
7952 7970
7953 tg3_reset_hw(tp);
7954
7955 mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) |
7956 MAC_MODE_PORT_INT_LPBACK | MAC_MODE_LINK_POLARITY |
7957 MAC_MODE_PORT_MODE_GMII;
7958 tw32(MAC_MODE, mac_mode);
7959
7960 tx_len = 1514; 7971 tx_len = 1514;
7961 skb = dev_alloc_skb(tx_len); 7972 skb = dev_alloc_skb(tx_len);
7962 tx_data = skb_put(skb, tx_len); 7973 tx_data = skb_put(skb, tx_len);
@@ -7977,15 +7988,15 @@ static int tg3_test_loopback(struct tg3 *tp)
7977 7988
7978 rx_start_idx = tp->hw_status->idx[0].rx_producer; 7989 rx_start_idx = tp->hw_status->idx[0].rx_producer;
7979 7990
7980 send_idx = 0;
7981 num_pkts = 0; 7991 num_pkts = 0;
7982 7992
7983 tg3_set_txd(tp, send_idx, map, tx_len, 0, 1); 7993 tg3_set_txd(tp, tp->tx_prod, map, tx_len, 0, 1);
7984 7994
7985 send_idx++; 7995 tp->tx_prod++;
7986 num_pkts++; 7996 num_pkts++;
7987 7997
7988 tw32_tx_mbox(MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW, send_idx); 7998 tw32_tx_mbox(MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW,
7999 tp->tx_prod);
7989 tr32_mailbox(MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW); 8000 tr32_mailbox(MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW);
7990 8001
7991 udelay(10); 8002 udelay(10);
@@ -7998,7 +8009,7 @@ static int tg3_test_loopback(struct tg3 *tp)
7998 8009
7999 tx_idx = tp->hw_status->idx[0].tx_consumer; 8010 tx_idx = tp->hw_status->idx[0].tx_consumer;
8000 rx_idx = tp->hw_status->idx[0].rx_producer; 8011 rx_idx = tp->hw_status->idx[0].rx_producer;
8001 if ((tx_idx == send_idx) && 8012 if ((tx_idx == tp->tx_prod) &&
8002 (rx_idx == (rx_start_idx + num_pkts))) 8013 (rx_idx == (rx_start_idx + num_pkts)))
8003 break; 8014 break;
8004 } 8015 }
@@ -8006,7 +8017,7 @@ static int tg3_test_loopback(struct tg3 *tp)
8006 pci_unmap_single(tp->pdev, map, tx_len, PCI_DMA_TODEVICE); 8017 pci_unmap_single(tp->pdev, map, tx_len, PCI_DMA_TODEVICE);
8007 dev_kfree_skb(skb); 8018 dev_kfree_skb(skb);
8008 8019
8009 if (tx_idx != send_idx) 8020 if (tx_idx != tp->tx_prod)
8010 goto out; 8021 goto out;
8011 8022
8012 if (rx_idx != rx_start_idx + num_pkts) 8023 if (rx_idx != rx_start_idx + num_pkts)
@@ -8042,6 +8053,30 @@ out:
8042 return err; 8053 return err;
8043} 8054}
8044 8055
8056#define TG3_MAC_LOOPBACK_FAILED 1
8057#define TG3_PHY_LOOPBACK_FAILED 2
8058#define TG3_LOOPBACK_FAILED (TG3_MAC_LOOPBACK_FAILED | \
8059 TG3_PHY_LOOPBACK_FAILED)
8060
8061static int tg3_test_loopback(struct tg3 *tp)
8062{
8063 int err = 0;
8064
8065 if (!netif_running(tp->dev))
8066 return TG3_LOOPBACK_FAILED;
8067
8068 tg3_reset_hw(tp);
8069
8070 if (tg3_run_loopback(tp, TG3_MAC_LOOPBACK))
8071 err |= TG3_MAC_LOOPBACK_FAILED;
8072 if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) {
8073 if (tg3_run_loopback(tp, TG3_PHY_LOOPBACK))
8074 err |= TG3_PHY_LOOPBACK_FAILED;
8075 }
8076
8077 return err;
8078}
8079
8045static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest, 8080static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest,
8046 u64 *data) 8081 u64 *data)
8047{ 8082{
@@ -8082,10 +8117,8 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest,
8082 etest->flags |= ETH_TEST_FL_FAILED; 8117 etest->flags |= ETH_TEST_FL_FAILED;
8083 data[3] = 1; 8118 data[3] = 1;
8084 } 8119 }
8085 if (tg3_test_loopback(tp) != 0) { 8120 if ((data[4] = tg3_test_loopback(tp)) != 0)
8086 etest->flags |= ETH_TEST_FL_FAILED; 8121 etest->flags |= ETH_TEST_FL_FAILED;
8087 data[4] = 1;
8088 }
8089 8122
8090 tg3_full_unlock(tp); 8123 tg3_full_unlock(tp);
8091 8124