aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorBen Hutchings <bhutchings@solarflare.com>2008-12-26 16:48:00 -0500
committerDavid S. Miller <davem@davemloft.net>2008-12-26 16:48:00 -0500
commit307505e9a4ce0b13b2f996385669039806e07390 (patch)
tree964307da71ddcd8b5bfcced1d701d80964a1b090 /drivers
parent1796721a5a691a5d392abf8070ad40a0b787b667 (diff)
sfc: SFT9001: Add cable diagnostics
The SFT9001 firmware implements cable diagnostics; run those and include their results in a self-test. In case of a cable fault, do not fail the self-test as a whole; only faults in the NIC should cause that. Signed-off-by: Ben Hutchings <bhutchings@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/sfc/tenxpress.c115
1 files changed, 107 insertions, 8 deletions
diff --git a/drivers/net/sfc/tenxpress.c b/drivers/net/sfc/tenxpress.c
index bd204820e18..b9768760fae 100644
--- a/drivers/net/sfc/tenxpress.c
+++ b/drivers/net/sfc/tenxpress.c
@@ -106,6 +106,25 @@
106#define PMA_PMD_SPEED_LBN 4 106#define PMA_PMD_SPEED_LBN 4
107#define PMA_PMD_SPEED_WIDTH 4 107#define PMA_PMD_SPEED_WIDTH 4
108 108
109/* Cable diagnostics - SFT9001 only */
110#define PMA_PMD_CDIAG_CTRL_REG 49213
111#define CDIAG_CTRL_IMMED_LBN 15
112#define CDIAG_CTRL_BRK_LINK_LBN 12
113#define CDIAG_CTRL_IN_PROG_LBN 11
114#define CDIAG_CTRL_LEN_UNIT_LBN 10
115#define CDIAG_CTRL_LEN_METRES 1
116#define PMA_PMD_CDIAG_RES_REG 49174
117#define CDIAG_RES_A_LBN 12
118#define CDIAG_RES_B_LBN 8
119#define CDIAG_RES_C_LBN 4
120#define CDIAG_RES_D_LBN 0
121#define CDIAG_RES_WIDTH 4
122#define CDIAG_RES_OPEN 2
123#define CDIAG_RES_OK 1
124#define CDIAG_RES_INVALID 0
125/* Set of 4 registers for pairs A-D */
126#define PMA_PMD_CDIAG_LEN_REG 49175
127
109/* Serdes control registers - SFT9001 only */ 128/* Serdes control registers - SFT9001 only */
110#define PMA_PMD_CSERDES_CTRL_REG 64258 129#define PMA_PMD_CSERDES_CTRL_REG 64258
111/* Set the 156.25 MHz output to 312.5 MHz to drive Falcon's XMAC */ 130/* Set the 156.25 MHz output to 312.5 MHz to drive Falcon's XMAC */
@@ -654,12 +673,12 @@ void tenxpress_phy_blink(struct efx_nic *efx, bool blink)
654 PMA_PMD_LED_OVERR_REG, reg); 673 PMA_PMD_LED_OVERR_REG, reg);
655} 674}
656 675
657static const char *const tenxpress_test_names[] = { 676static const char *const sfx7101_test_names[] = {
658 "bist" 677 "bist"
659}; 678};
660 679
661static int 680static int
662tenxpress_run_tests(struct efx_nic *efx, int *results, unsigned flags) 681sfx7101_run_tests(struct efx_nic *efx, int *results, unsigned flags)
663{ 682{
664 int rc; 683 int rc;
665 684
@@ -672,6 +691,86 @@ tenxpress_run_tests(struct efx_nic *efx, int *results, unsigned flags)
672 return rc; 691 return rc;
673} 692}
674 693
694static const char *const sft9001_test_names[] = {
695 "bist",
696 "cable.pairA.status",
697 "cable.pairB.status",
698 "cable.pairC.status",
699 "cable.pairD.status",
700 "cable.pairA.length",
701 "cable.pairB.length",
702 "cable.pairC.length",
703 "cable.pairD.length",
704};
705
706static int sft9001_run_tests(struct efx_nic *efx, int *results, unsigned flags)
707{
708 struct ethtool_cmd ecmd;
709 int phy_id = efx->mii.phy_id;
710 int rc = 0, rc2, i, res_reg;
711
712 if (!(flags & ETH_TEST_FL_OFFLINE))
713 return 0;
714
715 efx->phy_op->get_settings(efx, &ecmd);
716
717 /* Initialise cable diagnostic results to unknown failure */
718 for (i = 1; i < 9; ++i)
719 results[i] = -1;
720
721 /* Run cable diagnostics; wait up to 5 seconds for them to complete.
722 * A cable fault is not a self-test failure, but a timeout is. */
723 mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD,
724 PMA_PMD_CDIAG_CTRL_REG,
725 (1 << CDIAG_CTRL_IMMED_LBN) |
726 (1 << CDIAG_CTRL_BRK_LINK_LBN) |
727 (CDIAG_CTRL_LEN_METRES << CDIAG_CTRL_LEN_UNIT_LBN));
728 i = 0;
729 while (mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD,
730 PMA_PMD_CDIAG_CTRL_REG) &
731 (1 << CDIAG_CTRL_IN_PROG_LBN)) {
732 if (++i == 50) {
733 rc = -ETIMEDOUT;
734 goto reset;
735 }
736 msleep(100);
737 }
738 res_reg = mdio_clause45_read(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD,
739 PMA_PMD_CDIAG_RES_REG);
740 for (i = 0; i < 4; i++) {
741 int pair_res =
742 (res_reg >> (CDIAG_RES_A_LBN - i * CDIAG_RES_WIDTH))
743 & ((1 << CDIAG_RES_WIDTH) - 1);
744 int len_reg = mdio_clause45_read(efx, efx->mii.phy_id,
745 MDIO_MMD_PMAPMD,
746 PMA_PMD_CDIAG_LEN_REG + i);
747 if (pair_res == CDIAG_RES_OK)
748 results[1 + i] = 1;
749 else if (pair_res == CDIAG_RES_INVALID)
750 results[1 + i] = -1;
751 else
752 results[1 + i] = -pair_res;
753 if (pair_res != CDIAG_RES_INVALID &&
754 pair_res != CDIAG_RES_OPEN &&
755 len_reg != 0xffff)
756 results[5 + i] = len_reg;
757 }
758
759 /* We must reset to exit cable diagnostic mode. The BIST will
760 * also run when we do this. */
761reset:
762 rc2 = tenxpress_special_reset(efx);
763 results[0] = rc2 ? -1 : 1;
764 if (!rc)
765 rc = rc2;
766
767 rc2 = efx->phy_op->set_settings(efx, &ecmd);
768 if (!rc)
769 rc = rc2;
770
771 return rc;
772}
773
675static u32 tenxpress_get_xnp_lpa(struct efx_nic *efx) 774static u32 tenxpress_get_xnp_lpa(struct efx_nic *efx)
676{ 775{
677 int phy = efx->mii.phy_id; 776 int phy = efx->mii.phy_id;
@@ -784,9 +883,9 @@ struct efx_phy_operations falcon_sfx7101_phy_ops = {
784 .clear_interrupt = efx_port_dummy_op_void, 883 .clear_interrupt = efx_port_dummy_op_void,
785 .get_settings = sfx7101_get_settings, 884 .get_settings = sfx7101_get_settings,
786 .set_settings = mdio_clause45_set_settings, 885 .set_settings = mdio_clause45_set_settings,
787 .num_tests = ARRAY_SIZE(tenxpress_test_names), 886 .num_tests = ARRAY_SIZE(sfx7101_test_names),
788 .test_names = tenxpress_test_names, 887 .test_names = sfx7101_test_names,
789 .run_tests = tenxpress_run_tests, 888 .run_tests = sfx7101_run_tests,
790 .mmds = TENXPRESS_REQUIRED_DEVS, 889 .mmds = TENXPRESS_REQUIRED_DEVS,
791 .loopbacks = SFX7101_LOOPBACKS, 890 .loopbacks = SFX7101_LOOPBACKS,
792}; 891};
@@ -801,9 +900,9 @@ struct efx_phy_operations falcon_sft9001_phy_ops = {
801 .get_settings = sft9001_get_settings, 900 .get_settings = sft9001_get_settings,
802 .set_settings = sft9001_set_settings, 901 .set_settings = sft9001_set_settings,
803 .set_xnp_advertise = sft9001_set_xnp_advertise, 902 .set_xnp_advertise = sft9001_set_xnp_advertise,
804 .num_tests = ARRAY_SIZE(tenxpress_test_names), 903 .num_tests = ARRAY_SIZE(sft9001_test_names),
805 .test_names = tenxpress_test_names, 904 .test_names = sft9001_test_names,
806 .run_tests = tenxpress_run_tests, 905 .run_tests = sft9001_run_tests,
807 .mmds = TENXPRESS_REQUIRED_DEVS, 906 .mmds = TENXPRESS_REQUIRED_DEVS,
808 .loopbacks = SFT9001_LOOPBACKS, 907 .loopbacks = SFT9001_LOOPBACKS,
809}; 908};