diff options
-rw-r--r-- | drivers/infiniband/hw/hfi1/platform.c | 44 |
1 files changed, 43 insertions, 1 deletions
diff --git a/drivers/infiniband/hw/hfi1/platform.c b/drivers/infiniband/hw/hfi1/platform.c index 0e7043801bb1..838fe84e285a 100644 --- a/drivers/infiniband/hw/hfi1/platform.c +++ b/drivers/infiniband/hw/hfi1/platform.c | |||
@@ -637,6 +637,38 @@ static void apply_tx_lanes(struct hfi1_pportdata *ppd, u8 field_id, | |||
637 | } | 637 | } |
638 | } | 638 | } |
639 | 639 | ||
640 | /* | ||
641 | * Return a special SerDes setting for low power AOC cables. The power class | ||
642 | * threshold and setting being used were all found by empirical testing. | ||
643 | * | ||
644 | * Summary of the logic: | ||
645 | * | ||
646 | * if (QSFP and QSFP_TYPE == AOC and QSFP_POWER_CLASS < 4) | ||
647 | * return 0xe | ||
648 | * return 0; // leave at default | ||
649 | */ | ||
650 | static u8 aoc_low_power_setting(struct hfi1_pportdata *ppd) | ||
651 | { | ||
652 | u8 *cache = ppd->qsfp_info.cache; | ||
653 | int power_class; | ||
654 | |||
655 | /* QSFP only */ | ||
656 | if (ppd->port_type != PORT_TYPE_QSFP) | ||
657 | return 0; /* leave at default */ | ||
658 | |||
659 | /* active optical cables only */ | ||
660 | switch ((cache[QSFP_MOD_TECH_OFFS] & 0xF0) >> 4) { | ||
661 | case 0x0 ... 0x9: /* fallthrough */ | ||
662 | case 0xC: /* fallthrough */ | ||
663 | case 0xE: | ||
664 | /* active AOC */ | ||
665 | power_class = get_qsfp_power_class(cache[QSFP_MOD_PWR_OFFS]); | ||
666 | if (power_class < QSFP_POWER_CLASS_4) | ||
667 | return 0xe; | ||
668 | } | ||
669 | return 0; /* leave at default */ | ||
670 | } | ||
671 | |||
640 | static void apply_tunings( | 672 | static void apply_tunings( |
641 | struct hfi1_pportdata *ppd, u32 tx_preset_index, | 673 | struct hfi1_pportdata *ppd, u32 tx_preset_index, |
642 | u8 tuning_method, u32 total_atten, u8 limiting_active) | 674 | u8 tuning_method, u32 total_atten, u8 limiting_active) |
@@ -705,7 +737,17 @@ static void apply_tunings( | |||
705 | tx_preset_index, TX_PRESET_TABLE_POSTCUR, &tx_preset, 4); | 737 | tx_preset_index, TX_PRESET_TABLE_POSTCUR, &tx_preset, 4); |
706 | postcur = tx_preset; | 738 | postcur = tx_preset; |
707 | 739 | ||
708 | config_data = precur | (attn << 8) | (postcur << 16); | 740 | /* |
741 | * NOTES: | ||
742 | * o The aoc_low_power_setting is applied to all lanes even | ||
743 | * though only lane 0's value is examined by the firmware. | ||
744 | * o A lingering low power setting after a cable swap does | ||
745 | * not occur. On cable unplug the 8051 is reset and | ||
746 | * restarted on cable insert. This resets all settings to | ||
747 | * their default, erasing any previous low power setting. | ||
748 | */ | ||
749 | config_data = precur | (attn << 8) | (postcur << 16) | | ||
750 | (aoc_low_power_setting(ppd) << 24); | ||
709 | 751 | ||
710 | apply_tx_lanes(ppd, TX_EQ_SETTINGS, config_data, | 752 | apply_tx_lanes(ppd, TX_EQ_SETTINGS, config_data, |
711 | "Applying TX settings"); | 753 | "Applying TX settings"); |