diff options
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/tg3.c | 73 |
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 | ||
7938 | static int tg3_test_loopback(struct tg3 *tp) | 7938 | #define TG3_MAC_LOOPBACK 0 |
7939 | #define TG3_PHY_LOOPBACK 1 | ||
7940 | |||
7941 | static 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 | |||
8061 | static 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 | |||
8045 | static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest, | 8080 | static 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 | ||