diff options
Diffstat (limited to 'drivers/net/tg3.c')
| -rw-r--r-- | drivers/net/tg3.c | 571 | 
1 files changed, 556 insertions, 15 deletions
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index f10dd74988c4..fc9b5cd957aa 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c  | |||
| @@ -133,6 +133,8 @@ | |||
| 133 | /* number of ETHTOOL_GSTATS u64's */ | 133 | /* number of ETHTOOL_GSTATS u64's */ | 
| 134 | #define TG3_NUM_STATS (sizeof(struct tg3_ethtool_stats)/sizeof(u64)) | 134 | #define TG3_NUM_STATS (sizeof(struct tg3_ethtool_stats)/sizeof(u64)) | 
| 135 | 135 | ||
| 136 | #define TG3_NUM_TEST 6 | ||
| 137 | |||
| 136 | static char version[] __devinitdata = | 138 | static char version[] __devinitdata = | 
| 137 | DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; | 139 | DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; | 
| 138 | 140 | ||
| @@ -316,6 +318,17 @@ static struct { | |||
| 316 | { "nic_tx_threshold_hit" } | 318 | { "nic_tx_threshold_hit" } | 
| 317 | }; | 319 | }; | 
| 318 | 320 | ||
| 321 | static struct { | ||
| 322 | const char string[ETH_GSTRING_LEN]; | ||
| 323 | } ethtool_test_keys[TG3_NUM_TEST] = { | ||
| 324 | { "nvram test (online) " }, | ||
| 325 | { "link test (online) " }, | ||
| 326 | { "register test (offline)" }, | ||
| 327 | { "memory test (offline)" }, | ||
| 328 | { "loopback test (offline)" }, | ||
| 329 | { "interrupt test (offline)" }, | ||
| 330 | }; | ||
| 331 | |||
| 319 | static void tg3_write_indirect_reg32(struct tg3 *tp, u32 off, u32 val) | 332 | static void tg3_write_indirect_reg32(struct tg3 *tp, u32 off, u32 val) | 
| 320 | { | 333 | { | 
| 321 | if ((tp->tg3_flags & TG3_FLAG_PCIX_TARGET_HWBUG) != 0) { | 334 | if ((tp->tg3_flags & TG3_FLAG_PCIX_TARGET_HWBUG) != 0) { | 
| @@ -3070,7 +3083,7 @@ static irqreturn_t tg3_test_isr(int irq, void *dev_id, | |||
| 3070 | } | 3083 | } | 
| 3071 | 3084 | ||
| 3072 | static int tg3_init_hw(struct tg3 *); | 3085 | static int tg3_init_hw(struct tg3 *); | 
| 3073 | static int tg3_halt(struct tg3 *, int); | 3086 | static int tg3_halt(struct tg3 *, int, int); | 
| 3074 | 3087 | ||
| 3075 | #ifdef CONFIG_NET_POLL_CONTROLLER | 3088 | #ifdef CONFIG_NET_POLL_CONTROLLER | 
| 3076 | static void tg3_poll_controller(struct net_device *dev) | 3089 | static void tg3_poll_controller(struct net_device *dev) | 
| @@ -3094,7 +3107,7 @@ static void tg3_reset_task(void *_data) | |||
| 3094 | restart_timer = tp->tg3_flags2 & TG3_FLG2_RESTART_TIMER; | 3107 | restart_timer = tp->tg3_flags2 & TG3_FLG2_RESTART_TIMER; | 
| 3095 | tp->tg3_flags2 &= ~TG3_FLG2_RESTART_TIMER; | 3108 | tp->tg3_flags2 &= ~TG3_FLG2_RESTART_TIMER; | 
| 3096 | 3109 | ||
| 3097 | tg3_halt(tp, 0); | 3110 | tg3_halt(tp, RESET_KIND_SHUTDOWN, 0); | 
| 3098 | tg3_init_hw(tp); | 3111 | tg3_init_hw(tp); | 
| 3099 | 3112 | ||
| 3100 | tg3_netif_start(tp); | 3113 | tg3_netif_start(tp); | 
| @@ -3440,7 +3453,7 @@ static int tg3_change_mtu(struct net_device *dev, int new_mtu) | |||
| 3440 | spin_lock_irq(&tp->lock); | 3453 | spin_lock_irq(&tp->lock); | 
| 3441 | spin_lock(&tp->tx_lock); | 3454 | spin_lock(&tp->tx_lock); | 
| 3442 | 3455 | ||
| 3443 | tg3_halt(tp, 1); | 3456 | tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); | 
| 3444 | 3457 | ||
| 3445 | tg3_set_mtu(dev, tp, new_mtu); | 3458 | tg3_set_mtu(dev, tp, new_mtu); | 
| 3446 | 3459 | ||
| @@ -4131,19 +4144,19 @@ static void tg3_stop_fw(struct tg3 *tp) | |||
| 4131 | } | 4144 | } | 
| 4132 | 4145 | ||
| 4133 | /* tp->lock is held. */ | 4146 | /* tp->lock is held. */ | 
| 4134 | static int tg3_halt(struct tg3 *tp, int silent) | 4147 | static int tg3_halt(struct tg3 *tp, int kind, int silent) | 
| 4135 | { | 4148 | { | 
| 4136 | int err; | 4149 | int err; | 
| 4137 | 4150 | ||
| 4138 | tg3_stop_fw(tp); | 4151 | tg3_stop_fw(tp); | 
| 4139 | 4152 | ||
| 4140 | tg3_write_sig_pre_reset(tp, RESET_KIND_SHUTDOWN); | 4153 | tg3_write_sig_pre_reset(tp, kind); | 
| 4141 | 4154 | ||
| 4142 | tg3_abort_hw(tp, silent); | 4155 | tg3_abort_hw(tp, silent); | 
| 4143 | err = tg3_chip_reset(tp); | 4156 | err = tg3_chip_reset(tp); | 
| 4144 | 4157 | ||
| 4145 | tg3_write_sig_legacy(tp, RESET_KIND_SHUTDOWN); | 4158 | tg3_write_sig_legacy(tp, kind); | 
| 4146 | tg3_write_sig_post_reset(tp, RESET_KIND_SHUTDOWN); | 4159 | tg3_write_sig_post_reset(tp, kind); | 
| 4147 | 4160 | ||
| 4148 | if (err) | 4161 | if (err) | 
| 4149 | return err; | 4162 | return err; | 
| @@ -4357,7 +4370,12 @@ static int tg3_load_firmware_cpu(struct tg3 *tp, u32 cpu_base, u32 cpu_scratch_b | |||
| 4357 | */ | 4370 | */ | 
| 4358 | tp->tg3_flags |= TG3_FLAG_PCIX_TARGET_HWBUG; | 4371 | tp->tg3_flags |= TG3_FLAG_PCIX_TARGET_HWBUG; | 
| 4359 | 4372 | ||
| 4373 | /* It is possible that bootcode is still loading at this point. | ||
| 4374 | * Get the nvram lock first before halting the cpu. | ||
| 4375 | */ | ||
| 4376 | tg3_nvram_lock(tp); | ||
| 4360 | err = tg3_halt_cpu(tp, cpu_base); | 4377 | err = tg3_halt_cpu(tp, cpu_base); | 
| 4378 | tg3_nvram_unlock(tp); | ||
| 4361 | if (err) | 4379 | if (err) | 
| 4362 | goto out; | 4380 | goto out; | 
| 4363 | 4381 | ||
| @@ -5881,6 +5899,9 @@ static int tg3_test_interrupt(struct tg3 *tp) | |||
| 5881 | int err, i; | 5899 | int err, i; | 
| 5882 | u32 int_mbox = 0; | 5900 | u32 int_mbox = 0; | 
| 5883 | 5901 | ||
| 5902 | if (!netif_running(dev)) | ||
| 5903 | return -ENODEV; | ||
| 5904 | |||
| 5884 | tg3_disable_ints(tp); | 5905 | tg3_disable_ints(tp); | 
| 5885 | 5906 | ||
| 5886 | free_irq(tp->pdev->irq, dev); | 5907 | free_irq(tp->pdev->irq, dev); | 
| @@ -5984,7 +6005,7 @@ static int tg3_test_msi(struct tg3 *tp) | |||
| 5984 | spin_lock_irq(&tp->lock); | 6005 | spin_lock_irq(&tp->lock); | 
| 5985 | spin_lock(&tp->tx_lock); | 6006 | spin_lock(&tp->tx_lock); | 
| 5986 | 6007 | ||
| 5987 | tg3_halt(tp, 1); | 6008 | tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); | 
| 5988 | err = tg3_init_hw(tp); | 6009 | err = tg3_init_hw(tp); | 
| 5989 | 6010 | ||
| 5990 | spin_unlock(&tp->tx_lock); | 6011 | spin_unlock(&tp->tx_lock); | 
| @@ -6060,7 +6081,7 @@ static int tg3_open(struct net_device *dev) | |||
| 6060 | 6081 | ||
| 6061 | err = tg3_init_hw(tp); | 6082 | err = tg3_init_hw(tp); | 
| 6062 | if (err) { | 6083 | if (err) { | 
| 6063 | tg3_halt(tp, 1); | 6084 | tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); | 
| 6064 | tg3_free_rings(tp); | 6085 | tg3_free_rings(tp); | 
| 6065 | } else { | 6086 | } else { | 
| 6066 | if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) | 6087 | if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) | 
| @@ -6104,7 +6125,7 @@ static int tg3_open(struct net_device *dev) | |||
| 6104 | pci_disable_msi(tp->pdev); | 6125 | pci_disable_msi(tp->pdev); | 
| 6105 | tp->tg3_flags2 &= ~TG3_FLG2_USING_MSI; | 6126 | tp->tg3_flags2 &= ~TG3_FLG2_USING_MSI; | 
| 6106 | } | 6127 | } | 
| 6107 | tg3_halt(tp, 1); | 6128 | tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); | 
| 6108 | tg3_free_rings(tp); | 6129 | tg3_free_rings(tp); | 
| 6109 | tg3_free_consistent(tp); | 6130 | tg3_free_consistent(tp); | 
| 6110 | 6131 | ||
| @@ -6377,7 +6398,7 @@ static int tg3_close(struct net_device *dev) | |||
| 6377 | 6398 | ||
| 6378 | tg3_disable_ints(tp); | 6399 | tg3_disable_ints(tp); | 
| 6379 | 6400 | ||
| 6380 | tg3_halt(tp, 1); | 6401 | tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); | 
| 6381 | tg3_free_rings(tp); | 6402 | tg3_free_rings(tp); | 
| 6382 | tp->tg3_flags &= | 6403 | tp->tg3_flags &= | 
| 6383 | ~(TG3_FLAG_INIT_COMPLETE | | 6404 | ~(TG3_FLAG_INIT_COMPLETE | | 
| @@ -7097,7 +7118,7 @@ static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *e | |||
| 7097 | tp->tx_pending = ering->tx_pending; | 7118 | tp->tx_pending = ering->tx_pending; | 
| 7098 | 7119 | ||
| 7099 | if (netif_running(dev)) { | 7120 | if (netif_running(dev)) { | 
| 7100 | tg3_halt(tp, 1); | 7121 | tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); | 
| 7101 | tg3_init_hw(tp); | 7122 | tg3_init_hw(tp); | 
| 7102 | tg3_netif_start(tp); | 7123 | tg3_netif_start(tp); | 
| 7103 | } | 7124 | } | 
| @@ -7140,7 +7161,7 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam | |||
| 7140 | tp->tg3_flags &= ~TG3_FLAG_TX_PAUSE; | 7161 | tp->tg3_flags &= ~TG3_FLAG_TX_PAUSE; | 
| 7141 | 7162 | ||
| 7142 | if (netif_running(dev)) { | 7163 | if (netif_running(dev)) { | 
| 7143 | tg3_halt(tp, 1); | 7164 | tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); | 
| 7144 | tg3_init_hw(tp); | 7165 | tg3_init_hw(tp); | 
| 7145 | tg3_netif_start(tp); | 7166 | tg3_netif_start(tp); | 
| 7146 | } | 7167 | } | 
| @@ -7199,12 +7220,20 @@ static int tg3_get_stats_count (struct net_device *dev) | |||
| 7199 | return TG3_NUM_STATS; | 7220 | return TG3_NUM_STATS; | 
| 7200 | } | 7221 | } | 
| 7201 | 7222 | ||
| 7223 | static int tg3_get_test_count (struct net_device *dev) | ||
| 7224 | { | ||
| 7225 | return TG3_NUM_TEST; | ||
| 7226 | } | ||
| 7227 | |||
| 7202 | static void tg3_get_strings (struct net_device *dev, u32 stringset, u8 *buf) | 7228 | static void tg3_get_strings (struct net_device *dev, u32 stringset, u8 *buf) | 
| 7203 | { | 7229 | { | 
| 7204 | switch (stringset) { | 7230 | switch (stringset) { | 
| 7205 | case ETH_SS_STATS: | 7231 | case ETH_SS_STATS: | 
| 7206 | memcpy(buf, ðtool_stats_keys, sizeof(ethtool_stats_keys)); | 7232 | memcpy(buf, ðtool_stats_keys, sizeof(ethtool_stats_keys)); | 
| 7207 | break; | 7233 | break; | 
| 7234 | case ETH_SS_TEST: | ||
| 7235 | memcpy(buf, ðtool_test_keys, sizeof(ethtool_test_keys)); | ||
| 7236 | break; | ||
| 7208 | default: | 7237 | default: | 
| 7209 | WARN_ON(1); /* we need a WARN() */ | 7238 | WARN_ON(1); /* we need a WARN() */ | 
| 7210 | break; | 7239 | break; | 
| @@ -7218,6 +7247,516 @@ static void tg3_get_ethtool_stats (struct net_device *dev, | |||
| 7218 | memcpy(tmp_stats, tg3_get_estats(tp), sizeof(tp->estats)); | 7247 | memcpy(tmp_stats, tg3_get_estats(tp), sizeof(tp->estats)); | 
| 7219 | } | 7248 | } | 
| 7220 | 7249 | ||
| 7250 | #define NVRAM_TEST_SIZE 0x100 | ||
| 7251 | |||
| 7252 | static int tg3_test_nvram(struct tg3 *tp) | ||
| 7253 | { | ||
| 7254 | u32 *buf, csum; | ||
| 7255 | int i, j, err = 0; | ||
| 7256 | |||
| 7257 | buf = kmalloc(NVRAM_TEST_SIZE, GFP_KERNEL); | ||
| 7258 | if (buf == NULL) | ||
| 7259 | return -ENOMEM; | ||
| 7260 | |||
| 7261 | for (i = 0, j = 0; i < NVRAM_TEST_SIZE; i += 4, j++) { | ||
| 7262 | u32 val; | ||
| 7263 | |||
| 7264 | if ((err = tg3_nvram_read(tp, i, &val)) != 0) | ||
| 7265 | break; | ||
| 7266 | buf[j] = cpu_to_le32(val); | ||
| 7267 | } | ||
| 7268 | if (i < NVRAM_TEST_SIZE) | ||
| 7269 | goto out; | ||
| 7270 | |||
| 7271 | err = -EIO; | ||
| 7272 | if (cpu_to_be32(buf[0]) != TG3_EEPROM_MAGIC) | ||
| 7273 | goto out; | ||
| 7274 | |||
| 7275 | /* Bootstrap checksum at offset 0x10 */ | ||
| 7276 | csum = calc_crc((unsigned char *) buf, 0x10); | ||
| 7277 | if(csum != cpu_to_le32(buf[0x10/4])) | ||
| 7278 | goto out; | ||
| 7279 | |||
| 7280 | /* Manufacturing block starts at offset 0x74, checksum at 0xfc */ | ||
| 7281 | csum = calc_crc((unsigned char *) &buf[0x74/4], 0x88); | ||
| 7282 | if (csum != cpu_to_le32(buf[0xfc/4])) | ||
| 7283 | goto out; | ||
| 7284 | |||
| 7285 | err = 0; | ||
| 7286 | |||
| 7287 | out: | ||
| 7288 | kfree(buf); | ||
| 7289 | return err; | ||
| 7290 | } | ||
| 7291 | |||
| 7292 | #define TG3_SERDES_TIMEOUT_SEC 2 | ||
| 7293 | #define TG3_COPPER_TIMEOUT_SEC 6 | ||
| 7294 | |||
| 7295 | static int tg3_test_link(struct tg3 *tp) | ||
| 7296 | { | ||
| 7297 | int i, max; | ||
| 7298 | |||
| 7299 | if (!netif_running(tp->dev)) | ||
| 7300 | return -ENODEV; | ||
| 7301 | |||
| 7302 | if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) | ||
| 7303 | max = TG3_SERDES_TIMEOUT_SEC; | ||
| 7304 | else | ||
| 7305 | max = TG3_COPPER_TIMEOUT_SEC; | ||
| 7306 | |||
| 7307 | for (i = 0; i < max; i++) { | ||
| 7308 | if (netif_carrier_ok(tp->dev)) | ||
| 7309 | return 0; | ||
| 7310 | |||
| 7311 | if (msleep_interruptible(1000)) | ||
| 7312 | break; | ||
| 7313 | } | ||
| 7314 | |||
| 7315 | return -EIO; | ||
| 7316 | } | ||
| 7317 | |||
| 7318 | /* Only test the commonly used registers */ | ||
| 7319 | static int tg3_test_registers(struct tg3 *tp) | ||
| 7320 | { | ||
| 7321 | int i, is_5705; | ||
| 7322 | u32 offset, read_mask, write_mask, val, save_val, read_val; | ||
| 7323 | static struct { | ||
| 7324 | u16 offset; | ||
| 7325 | u16 flags; | ||
| 7326 | #define TG3_FL_5705 0x1 | ||
| 7327 | #define TG3_FL_NOT_5705 0x2 | ||
| 7328 | #define TG3_FL_NOT_5788 0x4 | ||
| 7329 | u32 read_mask; | ||
| 7330 | u32 write_mask; | ||
| 7331 | } reg_tbl[] = { | ||
| 7332 | /* MAC Control Registers */ | ||
| 7333 | { MAC_MODE, TG3_FL_NOT_5705, | ||
| 7334 | 0x00000000, 0x00ef6f8c }, | ||
| 7335 | { MAC_MODE, TG3_FL_5705, | ||
| 7336 | 0x00000000, 0x01ef6b8c }, | ||
| 7337 | { MAC_STATUS, TG3_FL_NOT_5705, | ||
| 7338 | 0x03800107, 0x00000000 }, | ||
| 7339 | { MAC_STATUS, TG3_FL_5705, | ||
| 7340 | 0x03800100, 0x00000000 }, | ||
| 7341 | { MAC_ADDR_0_HIGH, 0x0000, | ||
| 7342 | 0x00000000, 0x0000ffff }, | ||
| 7343 | { MAC_ADDR_0_LOW, 0x0000, | ||
| 7344 | 0x00000000, 0xffffffff }, | ||
| 7345 | { MAC_RX_MTU_SIZE, 0x0000, | ||
| 7346 | 0x00000000, 0x0000ffff }, | ||
| 7347 | { MAC_TX_MODE, 0x0000, | ||
| 7348 | 0x00000000, 0x00000070 }, | ||
| 7349 | { MAC_TX_LENGTHS, 0x0000, | ||
| 7350 | 0x00000000, 0x00003fff }, | ||
| 7351 | { MAC_RX_MODE, TG3_FL_NOT_5705, | ||
| 7352 | 0x00000000, 0x000007fc }, | ||
| 7353 | { MAC_RX_MODE, TG3_FL_5705, | ||
| 7354 | 0x00000000, 0x000007dc }, | ||
| 7355 | { MAC_HASH_REG_0, 0x0000, | ||
| 7356 | 0x00000000, 0xffffffff }, | ||
| 7357 | { MAC_HASH_REG_1, 0x0000, | ||
| 7358 | 0x00000000, 0xffffffff }, | ||
| 7359 | { MAC_HASH_REG_2, 0x0000, | ||
| 7360 | 0x00000000, 0xffffffff }, | ||
| 7361 | { MAC_HASH_REG_3, 0x0000, | ||
| 7362 | 0x00000000, 0xffffffff }, | ||
| 7363 | |||
| 7364 | /* Receive Data and Receive BD Initiator Control Registers. */ | ||
| 7365 | { RCVDBDI_JUMBO_BD+0, TG3_FL_NOT_5705, | ||
| 7366 | 0x00000000, 0xffffffff }, | ||
| 7367 | { RCVDBDI_JUMBO_BD+4, TG3_FL_NOT_5705, | ||
| 7368 | 0x00000000, 0xffffffff }, | ||
| 7369 | { RCVDBDI_JUMBO_BD+8, TG3_FL_NOT_5705, | ||
| 7370 | 0x00000000, 0x00000003 }, | ||
| 7371 | { RCVDBDI_JUMBO_BD+0xc, TG3_FL_NOT_5705, | ||
| 7372 | 0x00000000, 0xffffffff }, | ||
| 7373 | { RCVDBDI_STD_BD+0, 0x0000, | ||
| 7374 | 0x00000000, 0xffffffff }, | ||
| 7375 | { RCVDBDI_STD_BD+4, 0x0000, | ||
| 7376 | 0x00000000, 0xffffffff }, | ||
| 7377 | { RCVDBDI_STD_BD+8, 0x0000, | ||
| 7378 | 0x00000000, 0xffff0002 }, | ||
| 7379 | { RCVDBDI_STD_BD+0xc, 0x0000, | ||
| 7380 | 0x00000000, 0xffffffff }, | ||
| 7381 | |||
| 7382 | /* Receive BD Initiator Control Registers. */ | ||
| 7383 | { RCVBDI_STD_THRESH, TG3_FL_NOT_5705, | ||
| 7384 | 0x00000000, 0xffffffff }, | ||
| 7385 | { RCVBDI_STD_THRESH, TG3_FL_5705, | ||
| 7386 | 0x00000000, 0x000003ff }, | ||
| 7387 | { RCVBDI_JUMBO_THRESH, TG3_FL_NOT_5705, | ||
| 7388 | 0x00000000, 0xffffffff }, | ||
| 7389 | |||
| 7390 | /* Host Coalescing Control Registers. */ | ||
| 7391 | { HOSTCC_MODE, TG3_FL_NOT_5705, | ||
| 7392 | 0x00000000, 0x00000004 }, | ||
| 7393 | { HOSTCC_MODE, TG3_FL_5705, | ||
| 7394 | 0x00000000, 0x000000f6 }, | ||
| 7395 | { HOSTCC_RXCOL_TICKS, TG3_FL_NOT_5705, | ||
| 7396 | 0x00000000, 0xffffffff }, | ||
| 7397 | { HOSTCC_RXCOL_TICKS, TG3_FL_5705, | ||
| 7398 | 0x00000000, 0x000003ff }, | ||
| 7399 | { HOSTCC_TXCOL_TICKS, TG3_FL_NOT_5705, | ||
| 7400 | 0x00000000, 0xffffffff }, | ||
| 7401 | { HOSTCC_TXCOL_TICKS, TG3_FL_5705, | ||
| 7402 | 0x00000000, 0x000003ff }, | ||
| 7403 | { HOSTCC_RXMAX_FRAMES, TG3_FL_NOT_5705, | ||
| 7404 | 0x00000000, 0xffffffff }, | ||
| 7405 | { HOSTCC_RXMAX_FRAMES, TG3_FL_5705 | TG3_FL_NOT_5788, | ||
| 7406 | 0x00000000, 0x000000ff }, | ||
| 7407 | { HOSTCC_TXMAX_FRAMES, TG3_FL_NOT_5705, | ||
| 7408 | 0x00000000, 0xffffffff }, | ||
| 7409 | { HOSTCC_TXMAX_FRAMES, TG3_FL_5705 | TG3_FL_NOT_5788, | ||
| 7410 | 0x00000000, 0x000000ff }, | ||
| 7411 | { HOSTCC_RXCOAL_TICK_INT, TG3_FL_NOT_5705, | ||
| 7412 | 0x00000000, 0xffffffff }, | ||
| 7413 | { HOSTCC_TXCOAL_TICK_INT, TG3_FL_NOT_5705, | ||
| 7414 | 0x00000000, 0xffffffff }, | ||
| 7415 | { HOSTCC_RXCOAL_MAXF_INT, TG3_FL_NOT_5705, | ||
| 7416 | 0x00000000, 0xffffffff }, | ||
| 7417 | { HOSTCC_RXCOAL_MAXF_INT, TG3_FL_5705 | TG3_FL_NOT_5788, | ||
| 7418 | 0x00000000, 0x000000ff }, | ||
| 7419 | { HOSTCC_TXCOAL_MAXF_INT, TG3_FL_NOT_5705, | ||
| 7420 | 0x00000000, 0xffffffff }, | ||
| 7421 | { HOSTCC_TXCOAL_MAXF_INT, TG3_FL_5705 | TG3_FL_NOT_5788, | ||
| 7422 | 0x00000000, 0x000000ff }, | ||
| 7423 | { HOSTCC_STAT_COAL_TICKS, TG3_FL_NOT_5705, | ||
| 7424 | 0x00000000, 0xffffffff }, | ||
| 7425 | { HOSTCC_STATS_BLK_HOST_ADDR, TG3_FL_NOT_5705, | ||
| 7426 | 0x00000000, 0xffffffff }, | ||
| 7427 | { HOSTCC_STATS_BLK_HOST_ADDR+4, TG3_FL_NOT_5705, | ||
| 7428 | 0x00000000, 0xffffffff }, | ||
| 7429 | { HOSTCC_STATUS_BLK_HOST_ADDR, 0x0000, | ||
| 7430 | 0x00000000, 0xffffffff }, | ||
| 7431 | { HOSTCC_STATUS_BLK_HOST_ADDR+4, 0x0000, | ||
| 7432 | 0x00000000, 0xffffffff }, | ||
| 7433 | { HOSTCC_STATS_BLK_NIC_ADDR, 0x0000, | ||
| 7434 | 0xffffffff, 0x00000000 }, | ||
| 7435 | { HOSTCC_STATUS_BLK_NIC_ADDR, 0x0000, | ||
| 7436 | 0xffffffff, 0x00000000 }, | ||
| 7437 | |||
| 7438 | /* Buffer Manager Control Registers. */ | ||
| 7439 | { BUFMGR_MB_POOL_ADDR, 0x0000, | ||
| 7440 | 0x00000000, 0x007fff80 }, | ||
| 7441 | { BUFMGR_MB_POOL_SIZE, 0x0000, | ||
| 7442 | 0x00000000, 0x007fffff }, | ||
| 7443 | { BUFMGR_MB_RDMA_LOW_WATER, 0x0000, | ||
| 7444 | 0x00000000, 0x0000003f }, | ||
| 7445 | { BUFMGR_MB_MACRX_LOW_WATER, 0x0000, | ||
| 7446 | 0x00000000, 0x000001ff }, | ||
| 7447 | { BUFMGR_MB_HIGH_WATER, 0x0000, | ||
| 7448 | 0x00000000, 0x000001ff }, | ||
| 7449 | { BUFMGR_DMA_DESC_POOL_ADDR, TG3_FL_NOT_5705, | ||
| 7450 | 0xffffffff, 0x00000000 }, | ||
| 7451 | { BUFMGR_DMA_DESC_POOL_SIZE, TG3_FL_NOT_5705, | ||
| 7452 | 0xffffffff, 0x00000000 }, | ||
| 7453 | |||
| 7454 | /* Mailbox Registers */ | ||
| 7455 | { GRCMBOX_RCVSTD_PROD_IDX+4, 0x0000, | ||
| 7456 | 0x00000000, 0x000001ff }, | ||
| 7457 | { GRCMBOX_RCVJUMBO_PROD_IDX+4, TG3_FL_NOT_5705, | ||
| 7458 | 0x00000000, 0x000001ff }, | ||
| 7459 | { GRCMBOX_RCVRET_CON_IDX_0+4, 0x0000, | ||
| 7460 | 0x00000000, 0x000007ff }, | ||
| 7461 | { GRCMBOX_SNDHOST_PROD_IDX_0+4, 0x0000, | ||
| 7462 | 0x00000000, 0x000001ff }, | ||
| 7463 | |||
| 7464 | { 0xffff, 0x0000, 0x00000000, 0x00000000 }, | ||
| 7465 | }; | ||
| 7466 | |||
| 7467 | if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) | ||
| 7468 | is_5705 = 1; | ||
| 7469 | else | ||
| 7470 | is_5705 = 0; | ||
| 7471 | |||
| 7472 | for (i = 0; reg_tbl[i].offset != 0xffff; i++) { | ||
| 7473 | if (is_5705 && (reg_tbl[i].flags & TG3_FL_NOT_5705)) | ||
| 7474 | continue; | ||
| 7475 | |||
| 7476 | if (!is_5705 && (reg_tbl[i].flags & TG3_FL_5705)) | ||
| 7477 | continue; | ||
| 7478 | |||
| 7479 | if ((tp->tg3_flags2 & TG3_FLG2_IS_5788) && | ||
| 7480 | (reg_tbl[i].flags & TG3_FL_NOT_5788)) | ||
| 7481 | continue; | ||
| 7482 | |||
| 7483 | offset = (u32) reg_tbl[i].offset; | ||
| 7484 | read_mask = reg_tbl[i].read_mask; | ||
| 7485 | write_mask = reg_tbl[i].write_mask; | ||
| 7486 | |||
| 7487 | /* Save the original register content */ | ||
| 7488 | save_val = tr32(offset); | ||
| 7489 | |||
| 7490 | /* Determine the read-only value. */ | ||
| 7491 | read_val = save_val & read_mask; | ||
| 7492 | |||
| 7493 | /* Write zero to the register, then make sure the read-only bits | ||
| 7494 | * are not changed and the read/write bits are all zeros. | ||
| 7495 | */ | ||
| 7496 | tw32(offset, 0); | ||
| 7497 | |||
| 7498 | val = tr32(offset); | ||
| 7499 | |||
| 7500 | /* Test the read-only and read/write bits. */ | ||
| 7501 | if (((val & read_mask) != read_val) || (val & write_mask)) | ||
| 7502 | goto out; | ||
| 7503 | |||
| 7504 | /* Write ones to all the bits defined by RdMask and WrMask, then | ||
| 7505 | * make sure the read-only bits are not changed and the | ||
| 7506 | * read/write bits are all ones. | ||
| 7507 | */ | ||
| 7508 | tw32(offset, read_mask | write_mask); | ||
| 7509 | |||
| 7510 | val = tr32(offset); | ||
| 7511 | |||
| 7512 | /* Test the read-only bits. */ | ||
| 7513 | if ((val & read_mask) != read_val) | ||
| 7514 | goto out; | ||
| 7515 | |||
| 7516 | /* Test the read/write bits. */ | ||
| 7517 | if ((val & write_mask) != write_mask) | ||
| 7518 | goto out; | ||
| 7519 | |||
| 7520 | tw32(offset, save_val); | ||
| 7521 | } | ||
| 7522 | |||
| 7523 | return 0; | ||
| 7524 | |||
| 7525 | out: | ||
| 7526 | printk(KERN_ERR PFX "Register test failed at offset %x\n", offset); | ||
| 7527 | tw32(offset, save_val); | ||
| 7528 | return -EIO; | ||
| 7529 | } | ||
| 7530 | |||
| 7531 | static int tg3_do_mem_test(struct tg3 *tp, u32 offset, u32 len) | ||
| 7532 | { | ||
| 7533 | static u32 test_pattern[] = { 0x00000000, 0xffffffff, 0xaa55a55a }; | ||
| 7534 | int i; | ||
| 7535 | u32 j; | ||
| 7536 | |||
| 7537 | for (i = 0; i < sizeof(test_pattern)/sizeof(u32); i++) { | ||
| 7538 | for (j = 0; j < len; j += 4) { | ||
| 7539 | u32 val; | ||
| 7540 | |||
| 7541 | tg3_write_mem(tp, offset + j, test_pattern[i]); | ||
| 7542 | tg3_read_mem(tp, offset + j, &val); | ||
| 7543 | if (val != test_pattern[i]) | ||
| 7544 | return -EIO; | ||
| 7545 | } | ||
| 7546 | } | ||
| 7547 | return 0; | ||
| 7548 | } | ||
| 7549 | |||
| 7550 | static int tg3_test_memory(struct tg3 *tp) | ||
| 7551 | { | ||
| 7552 | static struct mem_entry { | ||
| 7553 | u32 offset; | ||
| 7554 | u32 len; | ||
| 7555 | } mem_tbl_570x[] = { | ||
| 7556 | { 0x00000000, 0x01000}, | ||
| 7557 | { 0x00002000, 0x1c000}, | ||
| 7558 | { 0xffffffff, 0x00000} | ||
| 7559 | }, mem_tbl_5705[] = { | ||
| 7560 | { 0x00000100, 0x0000c}, | ||
| 7561 | { 0x00000200, 0x00008}, | ||
| 7562 | { 0x00000b50, 0x00400}, | ||
| 7563 | { 0x00004000, 0x00800}, | ||
| 7564 | { 0x00006000, 0x01000}, | ||
| 7565 | { 0x00008000, 0x02000}, | ||
| 7566 | { 0x00010000, 0x0e000}, | ||
| 7567 | { 0xffffffff, 0x00000} | ||
| 7568 | }; | ||
| 7569 | struct mem_entry *mem_tbl; | ||
| 7570 | int err = 0; | ||
| 7571 | int i; | ||
| 7572 | |||
| 7573 | if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) | ||
| 7574 | mem_tbl = mem_tbl_5705; | ||
| 7575 | else | ||
| 7576 | mem_tbl = mem_tbl_570x; | ||
| 7577 | |||
| 7578 | for (i = 0; mem_tbl[i].offset != 0xffffffff; i++) { | ||
| 7579 | if ((err = tg3_do_mem_test(tp, mem_tbl[i].offset, | ||
| 7580 | mem_tbl[i].len)) != 0) | ||
| 7581 | break; | ||
| 7582 | } | ||
| 7583 | |||
| 7584 | return err; | ||
| 7585 | } | ||
| 7586 | |||
| 7587 | static int tg3_test_loopback(struct tg3 *tp) | ||
| 7588 | { | ||
| 7589 | u32 mac_mode, send_idx, rx_start_idx, rx_idx, tx_idx, opaque_key; | ||
| 7590 | u32 desc_idx; | ||
| 7591 | struct sk_buff *skb, *rx_skb; | ||
| 7592 | u8 *tx_data; | ||
| 7593 | dma_addr_t map; | ||
| 7594 | int num_pkts, tx_len, rx_len, i, err; | ||
| 7595 | struct tg3_rx_buffer_desc *desc; | ||
| 7596 | |||
| 7597 | if (!netif_running(tp->dev)) | ||
| 7598 | return -ENODEV; | ||
| 7599 | |||
| 7600 | err = -EIO; | ||
| 7601 | |||
| 7602 | tg3_abort_hw(tp, 1); | ||
| 7603 | |||
| 7604 | /* Clearing this flag to keep interrupts disabled */ | ||
| 7605 | tp->tg3_flags &= ~TG3_FLAG_INIT_COMPLETE; | ||
| 7606 | tg3_reset_hw(tp); | ||
| 7607 | |||
| 7608 | mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) | | ||
| 7609 | MAC_MODE_PORT_INT_LPBACK | MAC_MODE_LINK_POLARITY | | ||
| 7610 | MAC_MODE_PORT_MODE_GMII; | ||
| 7611 | tw32(MAC_MODE, mac_mode); | ||
| 7612 | |||
| 7613 | tx_len = 1514; | ||
| 7614 | skb = dev_alloc_skb(tx_len); | ||
| 7615 | tx_data = skb_put(skb, tx_len); | ||
| 7616 | memcpy(tx_data, tp->dev->dev_addr, 6); | ||
| 7617 | memset(tx_data + 6, 0x0, 8); | ||
| 7618 | |||
| 7619 | tw32(MAC_RX_MTU_SIZE, tx_len + 4); | ||
| 7620 | |||
| 7621 | for (i = 14; i < tx_len; i++) | ||
| 7622 | tx_data[i] = (u8) (i & 0xff); | ||
| 7623 | |||
| 7624 | map = pci_map_single(tp->pdev, skb->data, tx_len, PCI_DMA_TODEVICE); | ||
| 7625 | |||
| 7626 | tw32_f(HOSTCC_MODE, tp->coalesce_mode | HOSTCC_MODE_ENABLE | | ||
| 7627 | HOSTCC_MODE_NOW); | ||
| 7628 | |||
| 7629 | udelay(10); | ||
| 7630 | |||
| 7631 | rx_start_idx = tp->hw_status->idx[0].rx_producer; | ||
| 7632 | |||
| 7633 | send_idx = 0; | ||
| 7634 | num_pkts = 0; | ||
| 7635 | |||
| 7636 | tg3_set_txd(tp, send_idx, map, tx_len, 0, 1); | ||
| 7637 | |||
| 7638 | send_idx++; | ||
| 7639 | num_pkts++; | ||
| 7640 | |||
| 7641 | tw32_tx_mbox(MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW, send_idx); | ||
| 7642 | tr32(MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW); | ||
| 7643 | |||
| 7644 | udelay(10); | ||
| 7645 | |||
| 7646 | for (i = 0; i < 10; i++) { | ||
| 7647 | tw32_f(HOSTCC_MODE, tp->coalesce_mode | HOSTCC_MODE_ENABLE | | ||
| 7648 | HOSTCC_MODE_NOW); | ||
| 7649 | |||
| 7650 | udelay(10); | ||
| 7651 | |||
| 7652 | tx_idx = tp->hw_status->idx[0].tx_consumer; | ||
| 7653 | rx_idx = tp->hw_status->idx[0].rx_producer; | ||
| 7654 | if ((tx_idx == send_idx) && | ||
| 7655 | (rx_idx == (rx_start_idx + num_pkts))) | ||
| 7656 | break; | ||
| 7657 | } | ||
| 7658 | |||
| 7659 | pci_unmap_single(tp->pdev, map, tx_len, PCI_DMA_TODEVICE); | ||
| 7660 | dev_kfree_skb(skb); | ||
| 7661 | |||
| 7662 | if (tx_idx != send_idx) | ||
| 7663 | goto out; | ||
| 7664 | |||
| 7665 | if (rx_idx != rx_start_idx + num_pkts) | ||
| 7666 | goto out; | ||
| 7667 | |||
| 7668 | desc = &tp->rx_rcb[rx_start_idx]; | ||
| 7669 | desc_idx = desc->opaque & RXD_OPAQUE_INDEX_MASK; | ||
| 7670 | opaque_key = desc->opaque & RXD_OPAQUE_RING_MASK; | ||
| 7671 | if (opaque_key != RXD_OPAQUE_RING_STD) | ||
| 7672 | goto out; | ||
| 7673 | |||
| 7674 | if ((desc->err_vlan & RXD_ERR_MASK) != 0 && | ||
| 7675 | (desc->err_vlan != RXD_ERR_ODD_NIBBLE_RCVD_MII)) | ||
| 7676 | goto out; | ||
| 7677 | |||
| 7678 | rx_len = ((desc->idx_len & RXD_LEN_MASK) >> RXD_LEN_SHIFT) - 4; | ||
| 7679 | if (rx_len != tx_len) | ||
| 7680 | goto out; | ||
| 7681 | |||
| 7682 | rx_skb = tp->rx_std_buffers[desc_idx].skb; | ||
| 7683 | |||
| 7684 | map = pci_unmap_addr(&tp->rx_std_buffers[desc_idx], mapping); | ||
| 7685 | pci_dma_sync_single_for_cpu(tp->pdev, map, rx_len, PCI_DMA_FROMDEVICE); | ||
| 7686 | |||
| 7687 | for (i = 14; i < tx_len; i++) { | ||
| 7688 | if (*(rx_skb->data + i) != (u8) (i & 0xff)) | ||
| 7689 | goto out; | ||
| 7690 | } | ||
| 7691 | err = 0; | ||
| 7692 | |||
| 7693 | /* tg3_free_rings will unmap and free the rx_skb */ | ||
| 7694 | out: | ||
| 7695 | return err; | ||
| 7696 | } | ||
| 7697 | |||
| 7698 | static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest, | ||
| 7699 | u64 *data) | ||
| 7700 | { | ||
| 7701 | struct tg3 *tp = netdev_priv(dev); | ||
| 7702 | |||
| 7703 | memset(data, 0, sizeof(u64) * TG3_NUM_TEST); | ||
| 7704 | |||
| 7705 | if (tg3_test_nvram(tp) != 0) { | ||
| 7706 | etest->flags |= ETH_TEST_FL_FAILED; | ||
| 7707 | data[0] = 1; | ||
| 7708 | } | ||
| 7709 | if (tg3_test_link(tp) != 0) { | ||
| 7710 | etest->flags |= ETH_TEST_FL_FAILED; | ||
| 7711 | data[1] = 1; | ||
| 7712 | } | ||
| 7713 | if (etest->flags & ETH_TEST_FL_OFFLINE) { | ||
| 7714 | if (netif_running(dev)) | ||
| 7715 | tg3_netif_stop(tp); | ||
| 7716 | |||
| 7717 | spin_lock_irq(&tp->lock); | ||
| 7718 | spin_lock(&tp->tx_lock); | ||
| 7719 | |||
| 7720 | tg3_halt(tp, RESET_KIND_SUSPEND, 1); | ||
| 7721 | tg3_nvram_lock(tp); | ||
| 7722 | tg3_halt_cpu(tp, RX_CPU_BASE); | ||
| 7723 | if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) | ||
| 7724 | tg3_halt_cpu(tp, TX_CPU_BASE); | ||
| 7725 | tg3_nvram_unlock(tp); | ||
| 7726 | |||
| 7727 | if (tg3_test_registers(tp) != 0) { | ||
| 7728 | etest->flags |= ETH_TEST_FL_FAILED; | ||
| 7729 | data[2] = 1; | ||
| 7730 | } | ||
| 7731 | if (tg3_test_memory(tp) != 0) { | ||
| 7732 | etest->flags |= ETH_TEST_FL_FAILED; | ||
| 7733 | data[3] = 1; | ||
| 7734 | } | ||
| 7735 | if (tg3_test_loopback(tp) != 0) { | ||
| 7736 | etest->flags |= ETH_TEST_FL_FAILED; | ||
| 7737 | data[4] = 1; | ||
| 7738 | } | ||
| 7739 | |||
| 7740 | spin_unlock(&tp->tx_lock); | ||
| 7741 | spin_unlock_irq(&tp->lock); | ||
| 7742 | if (tg3_test_interrupt(tp) != 0) { | ||
| 7743 | etest->flags |= ETH_TEST_FL_FAILED; | ||
| 7744 | data[5] = 1; | ||
| 7745 | } | ||
| 7746 | spin_lock_irq(&tp->lock); | ||
| 7747 | spin_lock(&tp->tx_lock); | ||
| 7748 | |||
| 7749 | tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); | ||
| 7750 | if (netif_running(dev)) { | ||
| 7751 | tp->tg3_flags |= TG3_FLAG_INIT_COMPLETE; | ||
| 7752 | tg3_init_hw(tp); | ||
| 7753 | tg3_netif_start(tp); | ||
| 7754 | } | ||
| 7755 | spin_unlock(&tp->tx_lock); | ||
| 7756 | spin_unlock_irq(&tp->lock); | ||
| 7757 | } | ||
| 7758 | } | ||
| 7759 | |||
| 7221 | static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | 7760 | static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | 
| 7222 | { | 7761 | { | 
| 7223 | struct mii_ioctl_data *data = if_mii(ifr); | 7762 | struct mii_ioctl_data *data = if_mii(ifr); | 
| @@ -7331,6 +7870,8 @@ static struct ethtool_ops tg3_ethtool_ops = { | |||
| 7331 | .get_tso = ethtool_op_get_tso, | 7870 | .get_tso = ethtool_op_get_tso, | 
| 7332 | .set_tso = tg3_set_tso, | 7871 | .set_tso = tg3_set_tso, | 
| 7333 | #endif | 7872 | #endif | 
| 7873 | .self_test_count = tg3_get_test_count, | ||
| 7874 | .self_test = tg3_self_test, | ||
| 7334 | .get_strings = tg3_get_strings, | 7875 | .get_strings = tg3_get_strings, | 
| 7335 | .get_stats_count = tg3_get_stats_count, | 7876 | .get_stats_count = tg3_get_stats_count, | 
| 7336 | .get_ethtool_stats = tg3_get_ethtool_stats, | 7877 | .get_ethtool_stats = tg3_get_ethtool_stats, | 
| @@ -9478,7 +10019,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, | |||
| 9478 | (tr32(WDMAC_MODE) & WDMAC_MODE_ENABLE)) { | 10019 | (tr32(WDMAC_MODE) & WDMAC_MODE_ENABLE)) { | 
| 9479 | pci_save_state(tp->pdev); | 10020 | pci_save_state(tp->pdev); | 
| 9480 | tw32(MEMARB_MODE, MEMARB_MODE_ENABLE); | 10021 | tw32(MEMARB_MODE, MEMARB_MODE_ENABLE); | 
| 9481 | tg3_halt(tp, 1); | 10022 | tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); | 
| 9482 | } | 10023 | } | 
| 9483 | 10024 | ||
| 9484 | err = tg3_test_dma(tp); | 10025 | err = tg3_test_dma(tp); | 
| @@ -9605,7 +10146,7 @@ static int tg3_suspend(struct pci_dev *pdev, pm_message_t state) | |||
| 9605 | 10146 | ||
| 9606 | spin_lock_irq(&tp->lock); | 10147 | spin_lock_irq(&tp->lock); | 
| 9607 | spin_lock(&tp->tx_lock); | 10148 | spin_lock(&tp->tx_lock); | 
| 9608 | tg3_halt(tp, 1); | 10149 | tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); | 
| 9609 | spin_unlock(&tp->tx_lock); | 10150 | spin_unlock(&tp->tx_lock); | 
| 9610 | spin_unlock_irq(&tp->lock); | 10151 | spin_unlock_irq(&tp->lock); | 
| 9611 | 10152 | ||
