aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/tg3.c
diff options
context:
space:
mode:
authorMichael Chan <mchan@broadcom.com>2005-05-29 17:58:11 -0400
committerDavid S. Miller <davem@davemloft.net>2005-05-29 17:58:11 -0400
commita71116d1f3b85a69fe3a3acec9223fefb4b1fc66 (patch)
treee3d5019a6b3f0eb874f4c9803ea0dc7ba338ae2c /drivers/net/tg3.c
parent944d980ecaabe44616a9e2d50101ce774f517bb6 (diff)
[TG3]: Add register test
Signed-off-by: Michael Chan <mchan@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/tg3.c')
-rw-r--r--drivers/net/tg3.c241
1 files changed, 241 insertions, 0 deletions
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 73f6e962ed5e..4589f8f90119 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -7307,6 +7307,219 @@ static int tg3_test_link(struct tg3 *tp)
7307 return -EIO; 7307 return -EIO;
7308} 7308}
7309 7309
7310/* Only test the commonly used registers */
7311static int tg3_test_registers(struct tg3 *tp)
7312{
7313 int i, is_5705;
7314 u32 offset, read_mask, write_mask, val, save_val, read_val;
7315 static struct {
7316 u16 offset;
7317 u16 flags;
7318#define TG3_FL_5705 0x1
7319#define TG3_FL_NOT_5705 0x2
7320#define TG3_FL_NOT_5788 0x4
7321 u32 read_mask;
7322 u32 write_mask;
7323 } reg_tbl[] = {
7324 /* MAC Control Registers */
7325 { MAC_MODE, TG3_FL_NOT_5705,
7326 0x00000000, 0x00ef6f8c },
7327 { MAC_MODE, TG3_FL_5705,
7328 0x00000000, 0x01ef6b8c },
7329 { MAC_STATUS, TG3_FL_NOT_5705,
7330 0x03800107, 0x00000000 },
7331 { MAC_STATUS, TG3_FL_5705,
7332 0x03800100, 0x00000000 },
7333 { MAC_ADDR_0_HIGH, 0x0000,
7334 0x00000000, 0x0000ffff },
7335 { MAC_ADDR_0_LOW, 0x0000,
7336 0x00000000, 0xffffffff },
7337 { MAC_RX_MTU_SIZE, 0x0000,
7338 0x00000000, 0x0000ffff },
7339 { MAC_TX_MODE, 0x0000,
7340 0x00000000, 0x00000070 },
7341 { MAC_TX_LENGTHS, 0x0000,
7342 0x00000000, 0x00003fff },
7343 { MAC_RX_MODE, TG3_FL_NOT_5705,
7344 0x00000000, 0x000007fc },
7345 { MAC_RX_MODE, TG3_FL_5705,
7346 0x00000000, 0x000007dc },
7347 { MAC_HASH_REG_0, 0x0000,
7348 0x00000000, 0xffffffff },
7349 { MAC_HASH_REG_1, 0x0000,
7350 0x00000000, 0xffffffff },
7351 { MAC_HASH_REG_2, 0x0000,
7352 0x00000000, 0xffffffff },
7353 { MAC_HASH_REG_3, 0x0000,
7354 0x00000000, 0xffffffff },
7355
7356 /* Receive Data and Receive BD Initiator Control Registers. */
7357 { RCVDBDI_JUMBO_BD+0, TG3_FL_NOT_5705,
7358 0x00000000, 0xffffffff },
7359 { RCVDBDI_JUMBO_BD+4, TG3_FL_NOT_5705,
7360 0x00000000, 0xffffffff },
7361 { RCVDBDI_JUMBO_BD+8, TG3_FL_NOT_5705,
7362 0x00000000, 0x00000003 },
7363 { RCVDBDI_JUMBO_BD+0xc, TG3_FL_NOT_5705,
7364 0x00000000, 0xffffffff },
7365 { RCVDBDI_STD_BD+0, 0x0000,
7366 0x00000000, 0xffffffff },
7367 { RCVDBDI_STD_BD+4, 0x0000,
7368 0x00000000, 0xffffffff },
7369 { RCVDBDI_STD_BD+8, 0x0000,
7370 0x00000000, 0xffff0002 },
7371 { RCVDBDI_STD_BD+0xc, 0x0000,
7372 0x00000000, 0xffffffff },
7373
7374 /* Receive BD Initiator Control Registers. */
7375 { RCVBDI_STD_THRESH, TG3_FL_NOT_5705,
7376 0x00000000, 0xffffffff },
7377 { RCVBDI_STD_THRESH, TG3_FL_5705,
7378 0x00000000, 0x000003ff },
7379 { RCVBDI_JUMBO_THRESH, TG3_FL_NOT_5705,
7380 0x00000000, 0xffffffff },
7381
7382 /* Host Coalescing Control Registers. */
7383 { HOSTCC_MODE, TG3_FL_NOT_5705,
7384 0x00000000, 0x00000004 },
7385 { HOSTCC_MODE, TG3_FL_5705,
7386 0x00000000, 0x000000f6 },
7387 { HOSTCC_RXCOL_TICKS, TG3_FL_NOT_5705,
7388 0x00000000, 0xffffffff },
7389 { HOSTCC_RXCOL_TICKS, TG3_FL_5705,
7390 0x00000000, 0x000003ff },
7391 { HOSTCC_TXCOL_TICKS, TG3_FL_NOT_5705,
7392 0x00000000, 0xffffffff },
7393 { HOSTCC_TXCOL_TICKS, TG3_FL_5705,
7394 0x00000000, 0x000003ff },
7395 { HOSTCC_RXMAX_FRAMES, TG3_FL_NOT_5705,
7396 0x00000000, 0xffffffff },
7397 { HOSTCC_RXMAX_FRAMES, TG3_FL_5705 | TG3_FL_NOT_5788,
7398 0x00000000, 0x000000ff },
7399 { HOSTCC_TXMAX_FRAMES, TG3_FL_NOT_5705,
7400 0x00000000, 0xffffffff },
7401 { HOSTCC_TXMAX_FRAMES, TG3_FL_5705 | TG3_FL_NOT_5788,
7402 0x00000000, 0x000000ff },
7403 { HOSTCC_RXCOAL_TICK_INT, TG3_FL_NOT_5705,
7404 0x00000000, 0xffffffff },
7405 { HOSTCC_TXCOAL_TICK_INT, TG3_FL_NOT_5705,
7406 0x00000000, 0xffffffff },
7407 { HOSTCC_RXCOAL_MAXF_INT, TG3_FL_NOT_5705,
7408 0x00000000, 0xffffffff },
7409 { HOSTCC_RXCOAL_MAXF_INT, TG3_FL_5705 | TG3_FL_NOT_5788,
7410 0x00000000, 0x000000ff },
7411 { HOSTCC_TXCOAL_MAXF_INT, TG3_FL_NOT_5705,
7412 0x00000000, 0xffffffff },
7413 { HOSTCC_TXCOAL_MAXF_INT, TG3_FL_5705 | TG3_FL_NOT_5788,
7414 0x00000000, 0x000000ff },
7415 { HOSTCC_STAT_COAL_TICKS, TG3_FL_NOT_5705,
7416 0x00000000, 0xffffffff },
7417 { HOSTCC_STATS_BLK_HOST_ADDR, TG3_FL_NOT_5705,
7418 0x00000000, 0xffffffff },
7419 { HOSTCC_STATS_BLK_HOST_ADDR+4, TG3_FL_NOT_5705,
7420 0x00000000, 0xffffffff },
7421 { HOSTCC_STATUS_BLK_HOST_ADDR, 0x0000,
7422 0x00000000, 0xffffffff },
7423 { HOSTCC_STATUS_BLK_HOST_ADDR+4, 0x0000,
7424 0x00000000, 0xffffffff },
7425 { HOSTCC_STATS_BLK_NIC_ADDR, 0x0000,
7426 0xffffffff, 0x00000000 },
7427 { HOSTCC_STATUS_BLK_NIC_ADDR, 0x0000,
7428 0xffffffff, 0x00000000 },
7429
7430 /* Buffer Manager Control Registers. */
7431 { BUFMGR_MB_POOL_ADDR, 0x0000,
7432 0x00000000, 0x007fff80 },
7433 { BUFMGR_MB_POOL_SIZE, 0x0000,
7434 0x00000000, 0x007fffff },
7435 { BUFMGR_MB_RDMA_LOW_WATER, 0x0000,
7436 0x00000000, 0x0000003f },
7437 { BUFMGR_MB_MACRX_LOW_WATER, 0x0000,
7438 0x00000000, 0x000001ff },
7439 { BUFMGR_MB_HIGH_WATER, 0x0000,
7440 0x00000000, 0x000001ff },
7441 { BUFMGR_DMA_DESC_POOL_ADDR, TG3_FL_NOT_5705,
7442 0xffffffff, 0x00000000 },
7443 { BUFMGR_DMA_DESC_POOL_SIZE, TG3_FL_NOT_5705,
7444 0xffffffff, 0x00000000 },
7445
7446 /* Mailbox Registers */
7447 { GRCMBOX_RCVSTD_PROD_IDX+4, 0x0000,
7448 0x00000000, 0x000001ff },
7449 { GRCMBOX_RCVJUMBO_PROD_IDX+4, TG3_FL_NOT_5705,
7450 0x00000000, 0x000001ff },
7451 { GRCMBOX_RCVRET_CON_IDX_0+4, 0x0000,
7452 0x00000000, 0x000007ff },
7453 { GRCMBOX_SNDHOST_PROD_IDX_0+4, 0x0000,
7454 0x00000000, 0x000001ff },
7455
7456 { 0xffff, 0x0000, 0x00000000, 0x00000000 },
7457 };
7458
7459 if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS)
7460 is_5705 = 1;
7461 else
7462 is_5705 = 0;
7463
7464 for (i = 0; reg_tbl[i].offset != 0xffff; i++) {
7465 if (is_5705 && (reg_tbl[i].flags & TG3_FL_NOT_5705))
7466 continue;
7467
7468 if (!is_5705 && (reg_tbl[i].flags & TG3_FL_5705))
7469 continue;
7470
7471 if ((tp->tg3_flags2 & TG3_FLG2_IS_5788) &&
7472 (reg_tbl[i].flags & TG3_FL_NOT_5788))
7473 continue;
7474
7475 offset = (u32) reg_tbl[i].offset;
7476 read_mask = reg_tbl[i].read_mask;
7477 write_mask = reg_tbl[i].write_mask;
7478
7479 /* Save the original register content */
7480 save_val = tr32(offset);
7481
7482 /* Determine the read-only value. */
7483 read_val = save_val & read_mask;
7484
7485 /* Write zero to the register, then make sure the read-only bits
7486 * are not changed and the read/write bits are all zeros.
7487 */
7488 tw32(offset, 0);
7489
7490 val = tr32(offset);
7491
7492 /* Test the read-only and read/write bits. */
7493 if (((val & read_mask) != read_val) || (val & write_mask))
7494 goto out;
7495
7496 /* Write ones to all the bits defined by RdMask and WrMask, then
7497 * make sure the read-only bits are not changed and the
7498 * read/write bits are all ones.
7499 */
7500 tw32(offset, read_mask | write_mask);
7501
7502 val = tr32(offset);
7503
7504 /* Test the read-only bits. */
7505 if ((val & read_mask) != read_val)
7506 goto out;
7507
7508 /* Test the read/write bits. */
7509 if ((val & write_mask) != write_mask)
7510 goto out;
7511
7512 tw32(offset, save_val);
7513 }
7514
7515 return 0;
7516
7517out:
7518 printk(KERN_ERR PFX "Register test failed at offset %x\n", offset);
7519 tw32(offset, save_val);
7520 return -EIO;
7521}
7522
7310static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest, 7523static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest,
7311 u64 *data) 7524 u64 *data)
7312{ 7525{
@@ -7322,6 +7535,34 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest,
7322 etest->flags |= ETH_TEST_FL_FAILED; 7535 etest->flags |= ETH_TEST_FL_FAILED;
7323 data[1] = 1; 7536 data[1] = 1;
7324 } 7537 }
7538 if (etest->flags & ETH_TEST_FL_OFFLINE) {
7539 if (netif_running(dev))
7540 tg3_netif_stop(tp);
7541
7542 spin_lock_irq(&tp->lock);
7543 spin_lock(&tp->tx_lock);
7544
7545 tg3_halt(tp, RESET_KIND_SUSPEND, 1);
7546 tg3_nvram_lock(tp);
7547 tg3_halt_cpu(tp, RX_CPU_BASE);
7548 if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS))
7549 tg3_halt_cpu(tp, TX_CPU_BASE);
7550 tg3_nvram_unlock(tp);
7551
7552 if (tg3_test_registers(tp) != 0) {
7553 etest->flags |= ETH_TEST_FL_FAILED;
7554 data[2] = 1;
7555 }
7556
7557 tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
7558 if (netif_running(dev)) {
7559 tp->tg3_flags |= TG3_FLAG_INIT_COMPLETE;
7560 tg3_init_hw(tp);
7561 tg3_netif_start(tp);
7562 }
7563 spin_unlock(&tp->tx_lock);
7564 spin_unlock_irq(&tp->lock);
7565 }
7325} 7566}
7326 7567
7327static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) 7568static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)