diff options
author | Chien Tung <chien.tin.tung@intel.com> | 2009-04-08 17:27:18 -0400 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2009-04-08 17:27:18 -0400 |
commit | a4849fc157cdbe4fb68cfe37e7222697f003deb5 (patch) | |
tree | 315f1f55d5167b8006cf40d175b6eaae6914d43c /drivers/infiniband | |
parent | 1b9493248cf5e9f1ecc045488100cbf3ccd91be1 (diff) |
RDMA/nes: Add wide_ppm_offset parm for switch compatibility
We have observed unstable link with a new BNT switch.
Add wide_ppm_offset parameter to allow the user to control the clock
ppm offset on the CX4 interface for better compatibility. Default is
100ppm, setting it to 1 will increase it to 300ppm. Change default
SerDes1 reference clock to external source.
Signed-off-by: Chien Tung <chien.tin.tung@intel.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r-- | drivers/infiniband/hw/nes/nes_hw.c | 97 | ||||
-rw-r--r-- | drivers/infiniband/hw/nes/nes_hw.h | 1 |
2 files changed, 67 insertions, 31 deletions
diff --git a/drivers/infiniband/hw/nes/nes_hw.c b/drivers/infiniband/hw/nes/nes_hw.c index 466c730e6297..f797064315c2 100644 --- a/drivers/infiniband/hw/nes/nes_hw.c +++ b/drivers/infiniband/hw/nes/nes_hw.c | |||
@@ -46,6 +46,10 @@ static unsigned int nes_lro_max_aggr = NES_LRO_MAX_AGGR; | |||
46 | module_param(nes_lro_max_aggr, uint, 0444); | 46 | module_param(nes_lro_max_aggr, uint, 0444); |
47 | MODULE_PARM_DESC(nes_lro_max_aggr, "NIC LRO max packet aggregation"); | 47 | MODULE_PARM_DESC(nes_lro_max_aggr, "NIC LRO max packet aggregation"); |
48 | 48 | ||
49 | static int wide_ppm_offset; | ||
50 | module_param(wide_ppm_offset, int, 0644); | ||
51 | MODULE_PARM_DESC(wide_ppm_offset, "Increase CX4 interface clock ppm offset, 0=100ppm (default), 1=300ppm"); | ||
52 | |||
49 | static u32 crit_err_count; | 53 | static u32 crit_err_count; |
50 | u32 int_mod_timer_init; | 54 | u32 int_mod_timer_init; |
51 | u32 int_mod_cq_depth_256; | 55 | u32 int_mod_cq_depth_256; |
@@ -546,8 +550,11 @@ struct nes_adapter *nes_init_adapter(struct nes_device *nesdev, u8 hw_rev) { | |||
546 | msleep(1); | 550 | msleep(1); |
547 | } | 551 | } |
548 | if (int_cnt > 1) { | 552 | if (int_cnt > 1) { |
553 | u32 sds; | ||
549 | spin_lock_irqsave(&nesadapter->phy_lock, flags); | 554 | spin_lock_irqsave(&nesadapter->phy_lock, flags); |
550 | nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1, 0x0000F088); | 555 | sds = nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1); |
556 | sds |= 0x00000040; | ||
557 | nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1, sds); | ||
551 | mh_detected++; | 558 | mh_detected++; |
552 | reset_value = nes_read32(nesdev->regs+NES_SOFTWARE_RESET); | 559 | reset_value = nes_read32(nesdev->regs+NES_SOFTWARE_RESET); |
553 | reset_value |= 0x0000003d; | 560 | reset_value |= 0x0000003d; |
@@ -736,43 +743,48 @@ static int nes_init_serdes(struct nes_device *nesdev, u8 hw_rev, u8 port_count, | |||
736 | { | 743 | { |
737 | int i; | 744 | int i; |
738 | u32 u32temp; | 745 | u32 u32temp; |
739 | u32 serdes_common_control; | 746 | u32 sds; |
740 | 747 | ||
741 | if (hw_rev != NE020_REV) { | 748 | if (hw_rev != NE020_REV) { |
742 | /* init serdes 0 */ | 749 | /* init serdes 0 */ |
750 | if (wide_ppm_offset && (nesadapter->phy_type[0] == NES_PHY_TYPE_CX4)) | ||
751 | nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL0, 0x000FFFAA); | ||
752 | else | ||
753 | nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL0, 0x000000FF); | ||
743 | 754 | ||
744 | nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL0, 0x000000FF); | ||
745 | if (nesadapter->phy_type[0] == NES_PHY_TYPE_PUMA_1G) { | 755 | if (nesadapter->phy_type[0] == NES_PHY_TYPE_PUMA_1G) { |
746 | serdes_common_control = nes_read_indexed(nesdev, | 756 | sds = nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0); |
747 | NES_IDX_ETH_SERDES_COMMON_CONTROL0); | 757 | sds |= 0x00000100; |
748 | serdes_common_control |= 0x000000100; | 758 | nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0, sds); |
749 | nes_write_indexed(nesdev, | ||
750 | NES_IDX_ETH_SERDES_COMMON_CONTROL0, | ||
751 | serdes_common_control); | ||
752 | } else if (!OneG_Mode) { | ||
753 | nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_HIGHZ_LANE_MODE0, 0x11110000); | ||
754 | } | 759 | } |
755 | if (((port_count > 1) && | 760 | if (!OneG_Mode) |
756 | (nesadapter->phy_type[0] != NES_PHY_TYPE_PUMA_1G)) || | 761 | nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_HIGHZ_LANE_MODE0, 0x11110000); |
757 | ((port_count > 2) && | 762 | |
758 | (nesadapter->phy_type[0] == NES_PHY_TYPE_PUMA_1G))) { | 763 | if (port_count < 2) |
759 | /* init serdes 1 */ | 764 | return 0; |
760 | if (nesadapter->phy_type[0] == NES_PHY_TYPE_ARGUS) { | 765 | |
761 | nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_EMP0, 0x00000000); | 766 | /* init serdes 1 */ |
762 | nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_EMP1, 0x00000000); | 767 | switch (nesadapter->phy_type[1]) { |
763 | } | 768 | case NES_PHY_TYPE_ARGUS: |
764 | nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL1, 0x000000FF); | 769 | nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_EMP0, 0x00000000); |
765 | if (nesadapter->phy_type[0] == NES_PHY_TYPE_PUMA_1G) { | 770 | nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_EMP1, 0x00000000); |
766 | serdes_common_control = nes_read_indexed(nesdev, | 771 | break; |
767 | NES_IDX_ETH_SERDES_COMMON_CONTROL1); | 772 | case NES_PHY_TYPE_CX4: |
768 | serdes_common_control |= 0x000000100; | 773 | sds = nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1); |
769 | nes_write_indexed(nesdev, | 774 | sds &= 0xFFFFFFBF; |
770 | NES_IDX_ETH_SERDES_COMMON_CONTROL1, | 775 | nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1, sds); |
771 | serdes_common_control); | 776 | if (wide_ppm_offset) |
772 | } else if (!OneG_Mode) { | 777 | nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL1, 0x000FFFAA); |
773 | nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_HIGHZ_LANE_MODE1, 0x11110000); | 778 | else |
774 | } | 779 | nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL1, 0x000000FF); |
780 | break; | ||
781 | case NES_PHY_TYPE_PUMA_1G: | ||
782 | sds = nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1); | ||
783 | sds |= 0x000000100; | ||
784 | nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1, sds); | ||
775 | } | 785 | } |
786 | if (!OneG_Mode) | ||
787 | nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_HIGHZ_LANE_MODE1, 0x11110000); | ||
776 | } else { | 788 | } else { |
777 | /* init serdes 0 */ | 789 | /* init serdes 0 */ |
778 | nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0, 0x00000008); | 790 | nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0, 0x00000008); |
@@ -2315,6 +2327,7 @@ static void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number) | |||
2315 | u16 temp_phy_data; | 2327 | u16 temp_phy_data; |
2316 | u32 pcs_val = 0x0f0f0000; | 2328 | u32 pcs_val = 0x0f0f0000; |
2317 | u32 pcs_mask = 0x0f1f0000; | 2329 | u32 pcs_mask = 0x0f1f0000; |
2330 | u32 cdr_ctrl; | ||
2318 | 2331 | ||
2319 | spin_lock_irqsave(&nesadapter->phy_lock, flags); | 2332 | spin_lock_irqsave(&nesadapter->phy_lock, flags); |
2320 | if (nesadapter->mac_sw_state[mac_number] != NES_MAC_SW_IDLE) { | 2333 | if (nesadapter->mac_sw_state[mac_number] != NES_MAC_SW_IDLE) { |
@@ -2466,6 +2479,17 @@ static void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number) | |||
2466 | } | 2479 | } |
2467 | 2480 | ||
2468 | if (phy_data & 0x0004) { | 2481 | if (phy_data & 0x0004) { |
2482 | if (wide_ppm_offset && | ||
2483 | (nesadapter->phy_type[mac_index] == NES_PHY_TYPE_CX4) && | ||
2484 | (nesadapter->hw_rev != NE020_REV)) { | ||
2485 | cdr_ctrl = nes_read_indexed(nesdev, | ||
2486 | NES_IDX_ETH_SERDES_CDR_CONTROL0 + | ||
2487 | mac_index * 0x200); | ||
2488 | nes_write_indexed(nesdev, | ||
2489 | NES_IDX_ETH_SERDES_CDR_CONTROL0 + | ||
2490 | mac_index * 0x200, | ||
2491 | cdr_ctrl | 0x000F0000); | ||
2492 | } | ||
2469 | nesadapter->mac_link_down[mac_index] = 0; | 2493 | nesadapter->mac_link_down[mac_index] = 0; |
2470 | list_for_each_entry(nesvnic, &nesadapter->nesvnic_list[mac_index], list) { | 2494 | list_for_each_entry(nesvnic, &nesadapter->nesvnic_list[mac_index], list) { |
2471 | nes_debug(NES_DBG_PHY, "The Link is UP!!. linkup was %d\n", | 2495 | nes_debug(NES_DBG_PHY, "The Link is UP!!. linkup was %d\n", |
@@ -2480,6 +2504,17 @@ static void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number) | |||
2480 | } | 2504 | } |
2481 | } | 2505 | } |
2482 | } else { | 2506 | } else { |
2507 | if (wide_ppm_offset && | ||
2508 | (nesadapter->phy_type[mac_index] == NES_PHY_TYPE_CX4) && | ||
2509 | (nesadapter->hw_rev != NE020_REV)) { | ||
2510 | cdr_ctrl = nes_read_indexed(nesdev, | ||
2511 | NES_IDX_ETH_SERDES_CDR_CONTROL0 + | ||
2512 | mac_index * 0x200); | ||
2513 | nes_write_indexed(nesdev, | ||
2514 | NES_IDX_ETH_SERDES_CDR_CONTROL0 + | ||
2515 | mac_index * 0x200, | ||
2516 | cdr_ctrl & 0xFFF0FFFF); | ||
2517 | } | ||
2483 | nesadapter->mac_link_down[mac_index] = 1; | 2518 | nesadapter->mac_link_down[mac_index] = 1; |
2484 | list_for_each_entry(nesvnic, &nesadapter->nesvnic_list[mac_index], list) { | 2519 | list_for_each_entry(nesvnic, &nesadapter->nesvnic_list[mac_index], list) { |
2485 | nes_debug(NES_DBG_PHY, "The Link is Down!!. linkup was %d\n", | 2520 | nes_debug(NES_DBG_PHY, "The Link is Down!!. linkup was %d\n", |
diff --git a/drivers/infiniband/hw/nes/nes_hw.h b/drivers/infiniband/hw/nes/nes_hw.h index f41a8710d2a8..13bc26a83159 100644 --- a/drivers/infiniband/hw/nes/nes_hw.h +++ b/drivers/infiniband/hw/nes/nes_hw.h | |||
@@ -35,6 +35,7 @@ | |||
35 | 35 | ||
36 | #include <linux/inet_lro.h> | 36 | #include <linux/inet_lro.h> |
37 | 37 | ||
38 | #define NES_PHY_TYPE_CX4 1 | ||
38 | #define NES_PHY_TYPE_1G 2 | 39 | #define NES_PHY_TYPE_1G 2 |
39 | #define NES_PHY_TYPE_IRIS 3 | 40 | #define NES_PHY_TYPE_IRIS 3 |
40 | #define NES_PHY_TYPE_ARGUS 4 | 41 | #define NES_PHY_TYPE_ARGUS 4 |