diff mbox

[04/21] iwlwifi: mvm: avoid panics with thermal device usage

Message ID 1457545550-30677-4-git-send-email-emmanuel.grumbach@intel.com
State Accepted
Delegated to: Kalle Valo
Headers show

Commit Message

Emmanuel Grumbach March 9, 2016, 5:45 p.m. UTC
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>
---
 drivers/net/wireless/intel/iwlwifi/mvm/mvm.h |  1 -
 drivers/net/wireless/intel/iwlwifi/mvm/tt.c  | 57 +++++++++++++++-------------
 2 files changed, 31 insertions(+), 27 deletions(-)
diff mbox

Patch

diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
index ab410b4..b869db9 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
@@ -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);
 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_cooling_device_register(struct iwl_mvm *mvm);
 int iwl_mvm_ctdp_command(struct iwl_mvm *mvm, u32 op, u32 budget);
 
 /* Location Aware Regulatory */
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tt.c b/drivers/net/wireless/intel/iwlwifi/mvm/tt.c
index 999bcb8..0a02e98 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tt.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tt.c
@@ -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.
 	 * Avoid the deadlock by unlocking the mutex here.
 	 */
-	mutex_unlock(&mvm->mutex);
-	thermal_notify_framework(mvm->tz_device.tzone,
-				 mvm->tz_device.fw_trips_index[ths_crossed]);
-	mutex_lock(&mvm->mutex);
+	if (mvm->tz_device.tzone) {
+		struct iwl_mvm_thermal_device *tz_dev = &mvm->tz_device;
+
+		mutex_unlock(&mvm->mutex);
+		thermal_notify_framework(tz_dev->tzone,
+					 tz_dev->fw_trips_index[ths_crossed]);
+		mutex_lock(&mvm->mutex);
+	}
 #endif /* CONFIG_THERMAL */
 }
 
@@ -520,16 +524,20 @@  int iwl_mvm_send_temp_report_ths_cmd(struct iwl_mvm *mvm)
 
 	lockdep_assert_held(&mvm->mutex);
 
+	if (!mvm->tz_device.tzone)
+		return -EINVAL;
+
 	/* The driver holds array of temperature trips that are unsorted
 	 * and uncompressed, the FW should get it compressed and sorted
 	 */
 
 	/* 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) {
 			cmd.thresholds[idx++] =
 				cpu_to_le16(mvm->tz_device.temp_trips[i]);
 		}
+	}
 	cmd.num_temps = cpu_to_le32(idx);
 
 	if (!idx)
@@ -696,6 +704,7 @@  static void iwl_mvm_thermal_zone_register(struct iwl_mvm *mvm)
 		IWL_DEBUG_TEMP(mvm,
 			       "Failed to register to thermal zone (err = %ld)\n",
 			       PTR_ERR(mvm->tz_device.tzone));
+		mvm->tz_device.tzone = NULL;
 		return;
 	}
 
@@ -750,6 +759,10 @@  int iwl_mvm_ctdp_command(struct iwl_mvm *mvm, u32 op, u32 budget)
 		return ret;
 	}
 
+	/* can happen if the registration failed */
+	if (!mvm->cooling_dev.cdev)
+		return -EINVAL;
+
 	if (op == CTDP_CMD_OPERATION_START)
 		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,
 };
 
-int iwl_mvm_cooling_device_register(struct iwl_mvm *mvm)
+static void iwl_mvm_cooling_device_register(struct iwl_mvm *mvm)
 {
 	char name[] = "iwlwifi";
 
-	if (!iwl_mvm_is_ctdp_supported(mvm)) {
-		mvm->cooling_dev.cdev = NULL;
-
-		return 0;
-	}
+	if (!iwl_mvm_is_ctdp_supported(mvm))
+		return;
 
 	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,
 			       "Failed to register to cooling device (err = %ld)\n",
 			       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)
 {
-	if (!iwl_mvm_is_tt_in_fw(mvm))
+	if (!iwl_mvm_is_tt_in_fw(mvm) || !mvm->tz_device.tzone)
 		return;
 
-	if (mvm->tz_device.tzone) {
-		IWL_DEBUG_TEMP(mvm, "Thermal zone device unregister\n");
-		thermal_zone_device_unregister(mvm->tz_device.tzone);
-		mvm->tz_device.tzone = NULL;
-	}
+	IWL_DEBUG_TEMP(mvm, "Thermal zone device unregister\n");
+	thermal_zone_device_unregister(mvm->tz_device.tzone);
+	mvm->tz_device.tzone = NULL;
 }
 
 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;
 
-	if (mvm->cooling_dev.cdev) {
-		IWL_DEBUG_TEMP(mvm, "Cooling device unregister\n");
-		thermal_cooling_device_unregister(mvm->cooling_dev.cdev);
-		mvm->cooling_dev.cdev = NULL;
-	}
+	IWL_DEBUG_TEMP(mvm, "Cooling device unregister\n");
+	thermal_cooling_device_unregister(mvm->cooling_dev.cdev);
+	mvm->cooling_dev.cdev = NULL;
 }
 #endif /* CONFIG_THERMAL */