diff options
author | Chien Tung <chien.tin.tung@intel.com> | 2009-12-09 18:21:56 -0500 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2009-12-09 18:21:56 -0500 |
commit | a276510328d0721c252b37044c51e2fb4efe0364 (patch) | |
tree | 1a9d9632f919410cdbdada648ac1dc62ecca862c /drivers/infiniband/hw | |
parent | e293a26fe97c8598a96562c1c9376d9ae6cb96dd (diff) |
RDMA/nes: Add additional SFP+ PHY uC status check and PHY reset
Add additional PHY uC status check in case PHY firmware is not running
properly with heartbeat. Add a hard PHY reset if uC status is 0x0
after initial reset.
Signed-off-by: Chien Tung <chien.tin.tung@intel.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband/hw')
-rw-r--r-- | drivers/infiniband/hw/nes/nes_hw.c | 28 |
1 files changed, 22 insertions, 6 deletions
diff --git a/drivers/infiniband/hw/nes/nes_hw.c b/drivers/infiniband/hw/nes/nes_hw.c index 3d9bbff4f7ac..b59ca5659423 100644 --- a/drivers/infiniband/hw/nes/nes_hw.c +++ b/drivers/infiniband/hw/nes/nes_hw.c | |||
@@ -1356,6 +1356,8 @@ int nes_init_phy(struct nes_device *nesdev) | |||
1356 | } | 1356 | } |
1357 | if ((phy_type == NES_PHY_TYPE_ARGUS) || | 1357 | if ((phy_type == NES_PHY_TYPE_ARGUS) || |
1358 | (phy_type == NES_PHY_TYPE_SFP_D)) { | 1358 | (phy_type == NES_PHY_TYPE_SFP_D)) { |
1359 | u32 first_time = 1; | ||
1360 | |||
1359 | /* Check firmware heartbeat */ | 1361 | /* Check firmware heartbeat */ |
1360 | nes_read_10G_phy_reg(nesdev, phy_index, 0x3, 0xd7ee); | 1362 | nes_read_10G_phy_reg(nesdev, phy_index, 0x3, 0xd7ee); |
1361 | temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL); | 1363 | temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL); |
@@ -1363,8 +1365,13 @@ int nes_init_phy(struct nes_device *nesdev) | |||
1363 | nes_read_10G_phy_reg(nesdev, phy_index, 0x3, 0xd7ee); | 1365 | nes_read_10G_phy_reg(nesdev, phy_index, 0x3, 0xd7ee); |
1364 | temp_phy_data2 = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL); | 1366 | temp_phy_data2 = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL); |
1365 | 1367 | ||
1366 | if (temp_phy_data != temp_phy_data2) | 1368 | if (temp_phy_data != temp_phy_data2) { |
1367 | return 0; | 1369 | nes_read_10G_phy_reg(nesdev, phy_index, 0x3, 0xd7fd); |
1370 | temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL); | ||
1371 | if ((temp_phy_data & 0xff) > 0x20) | ||
1372 | return 0; | ||
1373 | printk(PFX "Reinitializing PHY\n"); | ||
1374 | } | ||
1368 | 1375 | ||
1369 | /* no heartbeat, configure the PHY */ | 1376 | /* no heartbeat, configure the PHY */ |
1370 | nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0x0000, 0x8000); | 1377 | nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0x0000, 0x8000); |
@@ -1400,7 +1407,7 @@ int nes_init_phy(struct nes_device *nesdev) | |||
1400 | temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL); | 1407 | temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL); |
1401 | do { | 1408 | do { |
1402 | if (counter++ > 150) { | 1409 | if (counter++ > 150) { |
1403 | nes_debug(NES_DBG_PHY, "No PHY heartbeat\n"); | 1410 | printk(PFX "No PHY heartbeat\n"); |
1404 | break; | 1411 | break; |
1405 | } | 1412 | } |
1406 | mdelay(1); | 1413 | mdelay(1); |
@@ -1414,11 +1421,20 @@ int nes_init_phy(struct nes_device *nesdev) | |||
1414 | nes_read_10G_phy_reg(nesdev, phy_index, 0x3, 0xd7fd); | 1421 | nes_read_10G_phy_reg(nesdev, phy_index, 0x3, 0xd7fd); |
1415 | temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL); | 1422 | temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL); |
1416 | if (counter++ > 300) { | 1423 | if (counter++ > 300) { |
1417 | nes_debug(NES_DBG_PHY, "PHY did not track\n"); | 1424 | if (((temp_phy_data & 0xff) == 0x0) && first_time) { |
1418 | break; | 1425 | first_time = 0; |
1426 | counter = 0; | ||
1427 | /* reset AMCC PHY and try again */ | ||
1428 | nes_write_10G_phy_reg(nesdev, phy_index, 0x3, 0xe854, 0x00c0); | ||
1429 | nes_write_10G_phy_reg(nesdev, phy_index, 0x3, 0xe854, 0x0040); | ||
1430 | continue; | ||
1431 | } else { | ||
1432 | printk(PFX "PHY did not track\n"); | ||
1433 | break; | ||
1434 | } | ||
1419 | } | 1435 | } |
1420 | mdelay(10); | 1436 | mdelay(10); |
1421 | } while (((temp_phy_data & 0xff) != 0x50) && ((temp_phy_data & 0xff) != 0x70)); | 1437 | } while ((temp_phy_data & 0xff) < 0x30); |
1422 | 1438 | ||
1423 | /* setup signal integrity */ | 1439 | /* setup signal integrity */ |
1424 | nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xd003, 0x0000); | 1440 | nes_write_10G_phy_reg(nesdev, phy_index, 0x1, 0xd003, 0x0000); |