Commit e4e0e39c authored by Dean Luick's avatar Dean Luick Committed by Doug Ledford

IB/hfi1: Fix double QSFP resource acquire on cache refresh

The function refresh_qsfp_cache() acquires the i2c chain resource,
but one caller already holds the resource.  Change the acquire so
all calls to refresh_qsfp_cache() are covered by the acquire and
remove the acquire within refresh_qsfp_cache().
Reviewed-by: default avatarEaswar Hariharan <easwar.hariharan@intel.com>
Signed-off-by: default avatarDean Luick <dean.luick@intel.com>
Signed-off-by: default avatarDoug Ledford <dledford@redhat.com>
parent 90315ad8
...@@ -603,6 +603,7 @@ static void apply_tunings( ...@@ -603,6 +603,7 @@ static void apply_tunings(
"Applying TX settings"); "Applying TX settings");
} }
/* Must be holding the QSFP i2c resource */
static int tune_active_qsfp(struct hfi1_pportdata *ppd, u32 *ptr_tx_preset, static int tune_active_qsfp(struct hfi1_pportdata *ppd, u32 *ptr_tx_preset,
u32 *ptr_rx_preset, u32 *ptr_total_atten) u32 *ptr_rx_preset, u32 *ptr_total_atten)
{ {
...@@ -610,26 +611,19 @@ static int tune_active_qsfp(struct hfi1_pportdata *ppd, u32 *ptr_tx_preset, ...@@ -610,26 +611,19 @@ static int tune_active_qsfp(struct hfi1_pportdata *ppd, u32 *ptr_tx_preset,
u16 lss = ppd->link_speed_supported, lse = ppd->link_speed_enabled; u16 lss = ppd->link_speed_supported, lse = ppd->link_speed_enabled;
u8 *cache = ppd->qsfp_info.cache; u8 *cache = ppd->qsfp_info.cache;
ret = acquire_chip_resource(ppd->dd, qsfp_resource(ppd->dd), QSFP_WAIT);
if (ret) {
dd_dev_err(ppd->dd, "%s: hfi%d: cannot lock i2c chain\n",
__func__, (int)ppd->dd->hfi1_id);
return ret;
}
ppd->qsfp_info.limiting_active = 1; ppd->qsfp_info.limiting_active = 1;
ret = set_qsfp_tx(ppd, 0); ret = set_qsfp_tx(ppd, 0);
if (ret) if (ret)
goto bail_unlock; return ret;
ret = qual_power(ppd); ret = qual_power(ppd);
if (ret) if (ret)
goto bail_unlock; return ret;
ret = qual_bitrate(ppd); ret = qual_bitrate(ppd);
if (ret) if (ret)
goto bail_unlock; return ret;
if (ppd->qsfp_info.reset_needed) { if (ppd->qsfp_info.reset_needed) {
reset_qsfp(ppd); reset_qsfp(ppd);
...@@ -641,7 +635,7 @@ static int tune_active_qsfp(struct hfi1_pportdata *ppd, u32 *ptr_tx_preset, ...@@ -641,7 +635,7 @@ static int tune_active_qsfp(struct hfi1_pportdata *ppd, u32 *ptr_tx_preset,
ret = set_qsfp_high_power(ppd); ret = set_qsfp_high_power(ppd);
if (ret) if (ret)
goto bail_unlock; return ret;
if (cache[QSFP_EQ_INFO_OFFS] & 0x4) { if (cache[QSFP_EQ_INFO_OFFS] & 0x4) {
ret = get_platform_config_field( ret = get_platform_config_field(
...@@ -651,7 +645,7 @@ static int tune_active_qsfp(struct hfi1_pportdata *ppd, u32 *ptr_tx_preset, ...@@ -651,7 +645,7 @@ static int tune_active_qsfp(struct hfi1_pportdata *ppd, u32 *ptr_tx_preset,
ptr_tx_preset, 4); ptr_tx_preset, 4);
if (ret) { if (ret) {
*ptr_tx_preset = OPA_INVALID_INDEX; *ptr_tx_preset = OPA_INVALID_INDEX;
goto bail_unlock; return ret;
} }
} else { } else {
ret = get_platform_config_field( ret = get_platform_config_field(
...@@ -661,7 +655,7 @@ static int tune_active_qsfp(struct hfi1_pportdata *ppd, u32 *ptr_tx_preset, ...@@ -661,7 +655,7 @@ static int tune_active_qsfp(struct hfi1_pportdata *ppd, u32 *ptr_tx_preset,
ptr_tx_preset, 4); ptr_tx_preset, 4);
if (ret) { if (ret) {
*ptr_tx_preset = OPA_INVALID_INDEX; *ptr_tx_preset = OPA_INVALID_INDEX;
goto bail_unlock; return ret;
} }
} }
...@@ -670,7 +664,7 @@ static int tune_active_qsfp(struct hfi1_pportdata *ppd, u32 *ptr_tx_preset, ...@@ -670,7 +664,7 @@ static int tune_active_qsfp(struct hfi1_pportdata *ppd, u32 *ptr_tx_preset,
PORT_TABLE_RX_PRESET_IDX, ptr_rx_preset, 4); PORT_TABLE_RX_PRESET_IDX, ptr_rx_preset, 4);
if (ret) { if (ret) {
*ptr_rx_preset = OPA_INVALID_INDEX; *ptr_rx_preset = OPA_INVALID_INDEX;
goto bail_unlock; return ret;
} }
if ((lss & OPA_LINK_SPEED_25G) && (lse & OPA_LINK_SPEED_25G)) if ((lss & OPA_LINK_SPEED_25G) && (lse & OPA_LINK_SPEED_25G))
...@@ -690,8 +684,6 @@ static int tune_active_qsfp(struct hfi1_pportdata *ppd, u32 *ptr_tx_preset, ...@@ -690,8 +684,6 @@ static int tune_active_qsfp(struct hfi1_pportdata *ppd, u32 *ptr_tx_preset,
ret = set_qsfp_tx(ppd, 1); ret = set_qsfp_tx(ppd, 1);
bail_unlock:
release_chip_resource(ppd->dd, qsfp_resource(ppd->dd));
return ret; return ret;
} }
...@@ -846,6 +838,14 @@ void tune_serdes(struct hfi1_pportdata *ppd) ...@@ -846,6 +838,14 @@ void tune_serdes(struct hfi1_pportdata *ppd)
break; break;
case PORT_TYPE_QSFP: case PORT_TYPE_QSFP:
if (qsfp_mod_present(ppd)) { if (qsfp_mod_present(ppd)) {
ret = acquire_chip_resource(ppd->dd,
qsfp_resource(ppd->dd),
QSFP_WAIT);
if (ret) {
dd_dev_err(ppd->dd, "%s: hfi%d: cannot lock i2c chain\n",
__func__, (int)ppd->dd->hfi1_id);
goto bail;
}
refresh_qsfp_cache(ppd, &ppd->qsfp_info); refresh_qsfp_cache(ppd, &ppd->qsfp_info);
if (ppd->qsfp_info.cache_valid) { if (ppd->qsfp_info.cache_valid) {
...@@ -860,17 +860,17 @@ void tune_serdes(struct hfi1_pportdata *ppd) ...@@ -860,17 +860,17 @@ void tune_serdes(struct hfi1_pportdata *ppd)
* update the cache to reflect the changes * update the cache to reflect the changes
*/ */
refresh_qsfp_cache(ppd, &ppd->qsfp_info); refresh_qsfp_cache(ppd, &ppd->qsfp_info);
if (ret)
goto bail;
limiting_active = limiting_active =
ppd->qsfp_info.limiting_active; ppd->qsfp_info.limiting_active;
} else { } else {
dd_dev_err(dd, dd_dev_err(dd,
"%s: Reading QSFP memory failed\n", "%s: Reading QSFP memory failed\n",
__func__); __func__);
goto bail; ret = -EINVAL; /* a fail indication */
} }
release_chip_resource(ppd->dd, qsfp_resource(ppd->dd));
if (ret)
goto bail;
} else { } else {
ppd->offline_disabled_reason = ppd->offline_disabled_reason =
HFI1_ODR_MASK( HFI1_ODR_MASK(
......
...@@ -355,6 +355,8 @@ int one_qsfp_read(struct hfi1_pportdata *ppd, u32 target, int addr, void *bp, ...@@ -355,6 +355,8 @@ int one_qsfp_read(struct hfi1_pportdata *ppd, u32 target, int addr, void *bp,
* The calls to qsfp_{read,write} in this function correctly handle the * The calls to qsfp_{read,write} in this function correctly handle the
* address map difference between this mapping and the mapping implemented * address map difference between this mapping and the mapping implemented
* by those functions * by those functions
*
* The caller must be holding the QSFP i2c chain resource.
*/ */
int refresh_qsfp_cache(struct hfi1_pportdata *ppd, struct qsfp_data *cp) int refresh_qsfp_cache(struct hfi1_pportdata *ppd, struct qsfp_data *cp)
{ {
...@@ -371,13 +373,9 @@ int refresh_qsfp_cache(struct hfi1_pportdata *ppd, struct qsfp_data *cp) ...@@ -371,13 +373,9 @@ int refresh_qsfp_cache(struct hfi1_pportdata *ppd, struct qsfp_data *cp)
if (!qsfp_mod_present(ppd)) { if (!qsfp_mod_present(ppd)) {
ret = -ENODEV; ret = -ENODEV;
goto bail_no_release; goto bail;
} }
ret = acquire_chip_resource(ppd->dd, qsfp_resource(ppd->dd), QSFP_WAIT);
if (ret)
goto bail_no_release;
ret = qsfp_read(ppd, target, 0, cache, QSFP_PAGESIZE); ret = qsfp_read(ppd, target, 0, cache, QSFP_PAGESIZE);
if (ret != QSFP_PAGESIZE) { if (ret != QSFP_PAGESIZE) {
dd_dev_info(ppd->dd, dd_dev_info(ppd->dd,
...@@ -440,8 +438,6 @@ int refresh_qsfp_cache(struct hfi1_pportdata *ppd, struct qsfp_data *cp) ...@@ -440,8 +438,6 @@ int refresh_qsfp_cache(struct hfi1_pportdata *ppd, struct qsfp_data *cp)
} }
} }
release_chip_resource(ppd->dd, qsfp_resource(ppd->dd));
spin_lock_irqsave(&ppd->qsfp_info.qsfp_lock, flags); spin_lock_irqsave(&ppd->qsfp_info.qsfp_lock, flags);
ppd->qsfp_info.cache_valid = 1; ppd->qsfp_info.cache_valid = 1;
ppd->qsfp_info.cache_refresh_required = 0; ppd->qsfp_info.cache_refresh_required = 0;
...@@ -450,8 +446,6 @@ int refresh_qsfp_cache(struct hfi1_pportdata *ppd, struct qsfp_data *cp) ...@@ -450,8 +446,6 @@ int refresh_qsfp_cache(struct hfi1_pportdata *ppd, struct qsfp_data *cp)
return 0; return 0;
bail: bail:
release_chip_resource(ppd->dd, qsfp_resource(ppd->dd));
bail_no_release:
memset(cache, 0, (QSFP_MAX_NUM_PAGES * 128)); memset(cache, 0, (QSFP_MAX_NUM_PAGES * 128));
return ret; return ret;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment