iwlwifi: mvm: avoid panics with thermal device usage

Thermal zone device registration can fail, and in this case
we don't want to remove WiFi functionality. This is why the
thermal zone registration function is void, and the flows
continue even if the thermal zone device registration failed.
Same applies for the cooling device.

This means that we at least need to remember that the thermal
zone device didn't register properly and take the minimal
precautions to avoid panic'ing when we access it.

This was missing.

Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
This commit is contained in:
Emmanuel Grumbach 2016-02-28 10:15:08 +02:00
parent e5f91d91ac
commit 91f66a3c67
2 changed files with 31 additions and 27 deletions

View File

@ -1575,7 +1575,6 @@ void iwl_mvm_set_hw_ctkill_state(struct iwl_mvm *mvm, bool state);
int iwl_mvm_get_temp(struct iwl_mvm *mvm, s32 *temp); int iwl_mvm_get_temp(struct iwl_mvm *mvm, s32 *temp);
void iwl_mvm_ct_kill_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb); void iwl_mvm_ct_kill_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb);
int iwl_mvm_send_temp_report_ths_cmd(struct iwl_mvm *mvm); int iwl_mvm_send_temp_report_ths_cmd(struct iwl_mvm *mvm);
int iwl_mvm_cooling_device_register(struct iwl_mvm *mvm);
int iwl_mvm_ctdp_command(struct iwl_mvm *mvm, u32 op, u32 budget); int iwl_mvm_ctdp_command(struct iwl_mvm *mvm, u32 op, u32 budget);
/* Location Aware Regulatory */ /* Location Aware Regulatory */

View File

@ -211,10 +211,14 @@ void iwl_mvm_temp_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb)
* the firmware and hence to take the mutex. * the firmware and hence to take the mutex.
* Avoid the deadlock by unlocking the mutex here. * Avoid the deadlock by unlocking the mutex here.
*/ */
mutex_unlock(&mvm->mutex); if (mvm->tz_device.tzone) {
thermal_notify_framework(mvm->tz_device.tzone, struct iwl_mvm_thermal_device *tz_dev = &mvm->tz_device;
mvm->tz_device.fw_trips_index[ths_crossed]);
mutex_lock(&mvm->mutex); mutex_unlock(&mvm->mutex);
thermal_notify_framework(tz_dev->tzone,
tz_dev->fw_trips_index[ths_crossed]);
mutex_lock(&mvm->mutex);
}
#endif /* CONFIG_THERMAL */ #endif /* CONFIG_THERMAL */
} }
@ -520,16 +524,20 @@ int iwl_mvm_send_temp_report_ths_cmd(struct iwl_mvm *mvm)
lockdep_assert_held(&mvm->mutex); lockdep_assert_held(&mvm->mutex);
if (!mvm->tz_device.tzone)
return -EINVAL;
/* The driver holds array of temperature trips that are unsorted /* The driver holds array of temperature trips that are unsorted
* and uncompressed, the FW should get it compressed and sorted * and uncompressed, the FW should get it compressed and sorted
*/ */
/* compress temp_trips to cmd array, remove uninitialized values*/ /* compress temp_trips to cmd array, remove uninitialized values*/
for (i = 0; i < IWL_MAX_DTS_TRIPS; i++) for (i = 0; i < IWL_MAX_DTS_TRIPS; i++) {
if (mvm->tz_device.temp_trips[i] != S16_MIN) { if (mvm->tz_device.temp_trips[i] != S16_MIN) {
cmd.thresholds[idx++] = cmd.thresholds[idx++] =
cpu_to_le16(mvm->tz_device.temp_trips[i]); cpu_to_le16(mvm->tz_device.temp_trips[i]);
} }
}
cmd.num_temps = cpu_to_le32(idx); cmd.num_temps = cpu_to_le32(idx);
if (!idx) if (!idx)
@ -696,6 +704,7 @@ static void iwl_mvm_thermal_zone_register(struct iwl_mvm *mvm)
IWL_DEBUG_TEMP(mvm, IWL_DEBUG_TEMP(mvm,
"Failed to register to thermal zone (err = %ld)\n", "Failed to register to thermal zone (err = %ld)\n",
PTR_ERR(mvm->tz_device.tzone)); PTR_ERR(mvm->tz_device.tzone));
mvm->tz_device.tzone = NULL;
return; return;
} }
@ -750,6 +759,10 @@ int iwl_mvm_ctdp_command(struct iwl_mvm *mvm, u32 op, u32 budget)
return ret; return ret;
} }
/* can happen if the registration failed */
if (!mvm->cooling_dev.cdev)
return -EINVAL;
if (op == CTDP_CMD_OPERATION_START) if (op == CTDP_CMD_OPERATION_START)
mvm->cooling_dev.cur_state = budget; mvm->cooling_dev.cur_state = budget;
@ -812,15 +825,12 @@ static struct thermal_cooling_device_ops tcooling_ops = {
.set_cur_state = iwl_mvm_tcool_set_cur_state, .set_cur_state = iwl_mvm_tcool_set_cur_state,
}; };
int iwl_mvm_cooling_device_register(struct iwl_mvm *mvm) static void iwl_mvm_cooling_device_register(struct iwl_mvm *mvm)
{ {
char name[] = "iwlwifi"; char name[] = "iwlwifi";
if (!iwl_mvm_is_ctdp_supported(mvm)) { if (!iwl_mvm_is_ctdp_supported(mvm))
mvm->cooling_dev.cdev = NULL; return;
return 0;
}
BUILD_BUG_ON(ARRAY_SIZE(name) >= THERMAL_NAME_LENGTH); BUILD_BUG_ON(ARRAY_SIZE(name) >= THERMAL_NAME_LENGTH);
@ -833,34 +843,29 @@ int iwl_mvm_cooling_device_register(struct iwl_mvm *mvm)
IWL_DEBUG_TEMP(mvm, IWL_DEBUG_TEMP(mvm,
"Failed to register to cooling device (err = %ld)\n", "Failed to register to cooling device (err = %ld)\n",
PTR_ERR(mvm->cooling_dev.cdev)); PTR_ERR(mvm->cooling_dev.cdev));
return PTR_ERR(mvm->cooling_dev.cdev); mvm->cooling_dev.cdev = NULL;
return;
} }
return 0;
} }
static void iwl_mvm_thermal_zone_unregister(struct iwl_mvm *mvm) static void iwl_mvm_thermal_zone_unregister(struct iwl_mvm *mvm)
{ {
if (!iwl_mvm_is_tt_in_fw(mvm)) if (!iwl_mvm_is_tt_in_fw(mvm) || !mvm->tz_device.tzone)
return; return;
if (mvm->tz_device.tzone) { IWL_DEBUG_TEMP(mvm, "Thermal zone device unregister\n");
IWL_DEBUG_TEMP(mvm, "Thermal zone device unregister\n"); thermal_zone_device_unregister(mvm->tz_device.tzone);
thermal_zone_device_unregister(mvm->tz_device.tzone); mvm->tz_device.tzone = NULL;
mvm->tz_device.tzone = NULL;
}
} }
static void iwl_mvm_cooling_device_unregister(struct iwl_mvm *mvm) static void iwl_mvm_cooling_device_unregister(struct iwl_mvm *mvm)
{ {
if (!iwl_mvm_is_ctdp_supported(mvm)) if (!iwl_mvm_is_ctdp_supported(mvm) || !mvm->cooling_dev.cdev)
return; return;
if (mvm->cooling_dev.cdev) { IWL_DEBUG_TEMP(mvm, "Cooling device unregister\n");
IWL_DEBUG_TEMP(mvm, "Cooling device unregister\n"); thermal_cooling_device_unregister(mvm->cooling_dev.cdev);
thermal_cooling_device_unregister(mvm->cooling_dev.cdev); mvm->cooling_dev.cdev = NULL;
mvm->cooling_dev.cdev = NULL;
}
} }
#endif /* CONFIG_THERMAL */ #endif /* CONFIG_THERMAL */