Skip to content

Commit 6e58c33

Browse files
kubalewskiPaolo Abeni
authored andcommitted
ice: fix crash on probe for DPLL enabled E810 LOM
The E810 Lan On Motherboard (LOM) design is vendor specific. Intel provides the reference design, but it is up to vendor on the final product design. For some cases, like Linux DPLL support, the static values defined in the driver does not reflect the actual LOM design. Current implementation of dpll pins is causing the crash on probe of the ice driver for such DPLL enabled E810 LOM designs: WARNING: (...) at drivers/dpll/dpll_core.c:495 dpll_pin_get+0x2c4/0x330 ... Call Trace: <TASK> ? __warn+0x83/0x130 ? dpll_pin_get+0x2c4/0x330 ? report_bug+0x1b7/0x1d0 ? handle_bug+0x42/0x70 ? exc_invalid_op+0x18/0x70 ? asm_exc_invalid_op+0x1a/0x20 ? dpll_pin_get+0x117/0x330 ? dpll_pin_get+0x2c4/0x330 ? dpll_pin_get+0x117/0x330 ice_dpll_get_pins.isra.0+0x52/0xe0 [ice] ... The number of dpll pins enabled by LOM vendor is greater than expected and defined in the driver for Intel designed NICs, which causes the crash. Prevent the crash and allow generic pin initialization within Linux DPLL subsystem for DPLL enabled E810 LOM designs. Newly designed solution for described issue will be based on "per HW design" pin initialization. It requires pin information dynamically acquired from the firmware and is already in progress, planned for next-tree only. Fixes: d7999f5 ("ice: implement dpll interface to control cgu") Reviewed-by: Karol Kolacinski <[email protected]> Signed-off-by: Arkadiusz Kubalewski <[email protected]> Tested-by: Pucha Himasekhar Reddy <[email protected]> Signed-off-by: Jacob Keller <[email protected]> Reviewed-by: Simon Horman <[email protected]> Signed-off-by: Paolo Abeni <[email protected]>
1 parent 3e13a8c commit 6e58c33

File tree

3 files changed

+90
-2
lines changed

3 files changed

+90
-2
lines changed

drivers/net/ethernet/intel/ice/ice_dpll.c

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#define ICE_DPLL_PIN_IDX_INVALID 0xff
1111
#define ICE_DPLL_RCLK_NUM_PER_PF 1
1212
#define ICE_DPLL_PIN_ESYNC_PULSE_HIGH_PERCENT 25
13+
#define ICE_DPLL_PIN_GEN_RCLK_FREQ 1953125
1314

1415
/**
1516
* enum ice_dpll_pin_type - enumerate ice pin types:
@@ -2063,6 +2064,73 @@ static int ice_dpll_init_worker(struct ice_pf *pf)
20632064
return 0;
20642065
}
20652066

2067+
/**
2068+
* ice_dpll_init_info_pins_generic - initializes generic pins info
2069+
* @pf: board private structure
2070+
* @input: if input pins initialized
2071+
*
2072+
* Init information for generic pins, cache them in PF's pins structures.
2073+
*
2074+
* Return:
2075+
* * 0 - success
2076+
* * negative - init failure reason
2077+
*/
2078+
static int ice_dpll_init_info_pins_generic(struct ice_pf *pf, bool input)
2079+
{
2080+
struct ice_dpll *de = &pf->dplls.eec, *dp = &pf->dplls.pps;
2081+
static const char labels[][sizeof("99")] = {
2082+
"0", "1", "2", "3", "4", "5", "6", "7", "8",
2083+
"9", "10", "11", "12", "13", "14", "15" };
2084+
u32 cap = DPLL_PIN_CAPABILITIES_STATE_CAN_CHANGE;
2085+
enum ice_dpll_pin_type pin_type;
2086+
int i, pin_num, ret = -EINVAL;
2087+
struct ice_dpll_pin *pins;
2088+
u32 phase_adj_max;
2089+
2090+
if (input) {
2091+
pin_num = pf->dplls.num_inputs;
2092+
pins = pf->dplls.inputs;
2093+
phase_adj_max = pf->dplls.input_phase_adj_max;
2094+
pin_type = ICE_DPLL_PIN_TYPE_INPUT;
2095+
cap |= DPLL_PIN_CAPABILITIES_PRIORITY_CAN_CHANGE;
2096+
} else {
2097+
pin_num = pf->dplls.num_outputs;
2098+
pins = pf->dplls.outputs;
2099+
phase_adj_max = pf->dplls.output_phase_adj_max;
2100+
pin_type = ICE_DPLL_PIN_TYPE_OUTPUT;
2101+
}
2102+
if (pin_num > ARRAY_SIZE(labels))
2103+
return ret;
2104+
2105+
for (i = 0; i < pin_num; i++) {
2106+
pins[i].idx = i;
2107+
pins[i].prop.board_label = labels[i];
2108+
pins[i].prop.phase_range.min = phase_adj_max;
2109+
pins[i].prop.phase_range.max = -phase_adj_max;
2110+
pins[i].prop.capabilities = cap;
2111+
pins[i].pf = pf;
2112+
ret = ice_dpll_pin_state_update(pf, &pins[i], pin_type, NULL);
2113+
if (ret)
2114+
break;
2115+
if (input && pins[i].freq == ICE_DPLL_PIN_GEN_RCLK_FREQ)
2116+
pins[i].prop.type = DPLL_PIN_TYPE_MUX;
2117+
else
2118+
pins[i].prop.type = DPLL_PIN_TYPE_EXT;
2119+
if (!input)
2120+
continue;
2121+
ret = ice_aq_get_cgu_ref_prio(&pf->hw, de->dpll_idx, i,
2122+
&de->input_prio[i]);
2123+
if (ret)
2124+
break;
2125+
ret = ice_aq_get_cgu_ref_prio(&pf->hw, dp->dpll_idx, i,
2126+
&dp->input_prio[i]);
2127+
if (ret)
2128+
break;
2129+
}
2130+
2131+
return ret;
2132+
}
2133+
20662134
/**
20672135
* ice_dpll_init_info_direct_pins - initializes direct pins info
20682136
* @pf: board private structure
@@ -2101,6 +2169,8 @@ ice_dpll_init_info_direct_pins(struct ice_pf *pf,
21012169
default:
21022170
return -EINVAL;
21032171
}
2172+
if (num_pins != ice_cgu_get_num_pins(hw, input))
2173+
return ice_dpll_init_info_pins_generic(pf, input);
21042174

21052175
for (i = 0; i < num_pins; i++) {
21062176
caps = 0;

drivers/net/ethernet/intel/ice/ice_ptp_hw.c

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ static const struct ice_cgu_pin_desc ice_e810t_sfp_cgu_inputs[] = {
3434
ARRAY_SIZE(ice_cgu_pin_freq_common), ice_cgu_pin_freq_common },
3535
{ "GNSS-1PPS", ZL_REF4P, DPLL_PIN_TYPE_GNSS,
3636
ARRAY_SIZE(ice_cgu_pin_freq_1_hz), ice_cgu_pin_freq_1_hz },
37-
{ "OCXO", ZL_REF4N, DPLL_PIN_TYPE_INT_OSCILLATOR, 0, },
3837
};
3938

4039
static const struct ice_cgu_pin_desc ice_e810t_qsfp_cgu_inputs[] = {
@@ -52,7 +51,6 @@ static const struct ice_cgu_pin_desc ice_e810t_qsfp_cgu_inputs[] = {
5251
ARRAY_SIZE(ice_cgu_pin_freq_common), ice_cgu_pin_freq_common },
5352
{ "GNSS-1PPS", ZL_REF4P, DPLL_PIN_TYPE_GNSS,
5453
ARRAY_SIZE(ice_cgu_pin_freq_1_hz), ice_cgu_pin_freq_1_hz },
55-
{ "OCXO", ZL_REF4N, DPLL_PIN_TYPE_INT_OSCILLATOR, },
5654
};
5755

5856
static const struct ice_cgu_pin_desc ice_e810t_sfp_cgu_outputs[] = {
@@ -5964,6 +5962,25 @@ ice_cgu_get_pin_desc(struct ice_hw *hw, bool input, int *size)
59645962
return t;
59655963
}
59665964

5965+
/**
5966+
* ice_cgu_get_num_pins - get pin description array size
5967+
* @hw: pointer to the hw struct
5968+
* @input: if request is done against input or output pins
5969+
*
5970+
* Return: size of pin description array for given hw.
5971+
*/
5972+
int ice_cgu_get_num_pins(struct ice_hw *hw, bool input)
5973+
{
5974+
const struct ice_cgu_pin_desc *t;
5975+
int size;
5976+
5977+
t = ice_cgu_get_pin_desc(hw, input, &size);
5978+
if (t)
5979+
return size;
5980+
5981+
return 0;
5982+
}
5983+
59675984
/**
59685985
* ice_cgu_get_pin_type - get pin's type
59695986
* @hw: pointer to the hw struct

drivers/net/ethernet/intel/ice/ice_ptp_hw.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,7 @@ int ice_read_sma_ctrl_e810t(struct ice_hw *hw, u8 *data);
404404
int ice_write_sma_ctrl_e810t(struct ice_hw *hw, u8 data);
405405
int ice_read_pca9575_reg_e810t(struct ice_hw *hw, u8 offset, u8 *data);
406406
bool ice_is_pca9575_present(struct ice_hw *hw);
407+
int ice_cgu_get_num_pins(struct ice_hw *hw, bool input);
407408
enum dpll_pin_type ice_cgu_get_pin_type(struct ice_hw *hw, u8 pin, bool input);
408409
struct dpll_pin_frequency *
409410
ice_cgu_get_pin_freq_supp(struct ice_hw *hw, u8 pin, bool input, u8 *num);

0 commit comments

Comments
 (0)