aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChaya Rachel Ivgi <chaya.rachel.ivgi@intel.com>2016-01-05 03:34:47 -0500
committerEmmanuel Grumbach <emmanuel.grumbach@intel.com>2016-02-27 14:59:50 -0500
commit5c89e7bc557e1dd5650946a0fe4940166bc62abf (patch)
treeb609cc8d79dad579851b02590500ca3340c57062
parentc221daf219b1cf38e7c4307f0f420ea826678af5 (diff)
iwlwifi: mvm: add registration to cooling device
Register cooling device in order to have the Thermal Manager handle the device's power budget according to the sent notifications. The interface adds a new thermal cooling device to /sys/class/thermal/ folder. Signed-off-by: Chaya Rachel Ivgi <chaya.rachel.ivgi@intel.com> Signed-off-by: Luca Coelho <luciano.coelho@intel.com> Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h26
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw.c5
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mvm.h19
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/ops.c1
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/tt.c147
6 files changed, 200 insertions, 0 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h b/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h
index 724a3eef78b1..63dc109605e3 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h
@@ -321,6 +321,7 @@ typedef unsigned int __bitwise__ iwl_ucode_tlv_capa_t;
321 * @IWL_UCODE_TLV_CAPA_CT_KILL_BY_FW: firmware responsible for CT-kill 321 * @IWL_UCODE_TLV_CAPA_CT_KILL_BY_FW: firmware responsible for CT-kill
322 * @IWL_UCODE_TLV_CAPA_TEMP_THS_REPORT_SUPPORT: supports temperature 322 * @IWL_UCODE_TLV_CAPA_TEMP_THS_REPORT_SUPPORT: supports temperature
323 * thresholds reporting 323 * thresholds reporting
324 * @IWL_UCODE_TLV_CAPA_CTDP_SUPPORT: supports cTDP command
324 * 325 *
325 * @NUM_IWL_UCODE_TLV_CAPA: number of bits used 326 * @NUM_IWL_UCODE_TLV_CAPA: number of bits used
326 */ 327 */
@@ -356,6 +357,7 @@ enum iwl_ucode_tlv_capa {
356 IWL_UCODE_TLV_CAPA_LAR_SUPPORT_V2 = (__force iwl_ucode_tlv_capa_t)73, 357 IWL_UCODE_TLV_CAPA_LAR_SUPPORT_V2 = (__force iwl_ucode_tlv_capa_t)73,
357 IWL_UCODE_TLV_CAPA_CT_KILL_BY_FW = (__force iwl_ucode_tlv_capa_t)74, 358 IWL_UCODE_TLV_CAPA_CT_KILL_BY_FW = (__force iwl_ucode_tlv_capa_t)74,
358 IWL_UCODE_TLV_CAPA_TEMP_THS_REPORT_SUPPORT = (__force iwl_ucode_tlv_capa_t)75, 359 IWL_UCODE_TLV_CAPA_TEMP_THS_REPORT_SUPPORT = (__force iwl_ucode_tlv_capa_t)75,
360 IWL_UCODE_TLV_CAPA_CTDP_SUPPORT = (__force iwl_ucode_tlv_capa_t)76,
359 361
360 NUM_IWL_UCODE_TLV_CAPA 362 NUM_IWL_UCODE_TLV_CAPA
361#ifdef __CHECKER__ 363#ifdef __CHECKER__
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h
index e692098a9f1e..d5f90371054e 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h
@@ -279,6 +279,7 @@ enum {
279 */ 279 */
280enum iwl_phy_ops_subcmd_ids { 280enum iwl_phy_ops_subcmd_ids {
281 CMD_DTS_MEASUREMENT_TRIGGER_WIDE = 0x0, 281 CMD_DTS_MEASUREMENT_TRIGGER_WIDE = 0x0,
282 CTDP_CONFIG_CMD = 0x03,
282 TEMP_REPORTING_THRESHOLDS_CMD = 0x04, 283 TEMP_REPORTING_THRESHOLDS_CMD = 0x04,
283 CT_KILL_NOTIFICATION = 0xFE, 284 CT_KILL_NOTIFICATION = 0xFE,
284 DTS_MEASUREMENT_NOTIF_WIDE = 0xFF, 285 DTS_MEASUREMENT_NOTIF_WIDE = 0xFF,
@@ -1711,6 +1712,31 @@ struct ct_kill_notif {
1711 __le16 reserved; 1712 __le16 reserved;
1712} __packed; /* GRP_PHY_CT_KILL_NTF */ 1713} __packed; /* GRP_PHY_CT_KILL_NTF */
1713 1714
1715/**
1716* enum ctdp_cmd_operation - CTDP command operations
1717* @CTDP_CMD_OPERATION_START: update the current budget
1718* @CTDP_CMD_OPERATION_STOP: stop ctdp
1719* @CTDP_CMD_OPERATION_REPORT: get the avgerage budget
1720*/
1721enum iwl_mvm_ctdp_cmd_operation {
1722 CTDP_CMD_OPERATION_START = 0x1,
1723 CTDP_CMD_OPERATION_STOP = 0x2,
1724 CTDP_CMD_OPERATION_REPORT = 0x4,
1725};/* CTDP_CMD_OPERATION_TYPE_E */
1726
1727/**
1728 * struct iwl_mvm_ctdp_cmd - track and manage the FW power consumption budget
1729 *
1730 * @operation: see &enum iwl_mvm_ctdp_cmd_operation
1731 * @budget: the budget in milliwatt
1732 * @window_size: defined in API but not used
1733 */
1734struct iwl_mvm_ctdp_cmd {
1735 __le32 operation;
1736 __le32 budget;
1737 __le32 window_size;
1738} __packed;
1739
1714#define IWL_MAX_DTS_TRIPS 8 1740#define IWL_MAX_DTS_TRIPS 8
1715 1741
1716/** 1742/**
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
index 07f2cbd9c8e7..3e596e4b3999 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
@@ -963,6 +963,11 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
963 /* Initialize tx backoffs to the minimal possible */ 963 /* Initialize tx backoffs to the minimal possible */
964 iwl_mvm_tt_tx_backoff(mvm, 0); 964 iwl_mvm_tt_tx_backoff(mvm, 0);
965 } 965 }
966
967 /* TODO: read the budget from BIOS / Platform NVM */
968 if (iwl_mvm_is_ctdp_supported(mvm) && mvm->cooling_dev.cur_state > 0)
969 ret = iwl_mvm_ctdp_command(mvm, CTDP_CMD_OPERATION_START,
970 mvm->cooling_dev.cur_state);
966#else 971#else
967 /* Initialize tx backoffs to the minimal possible */ 972 /* Initialize tx backoffs to the minimal possible */
968 iwl_mvm_tt_tx_backoff(mvm, 0); 973 iwl_mvm_tt_tx_backoff(mvm, 0);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
index 87d3e2884886..d867cb478681 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
@@ -535,6 +535,16 @@ struct iwl_mvm_thermal_device {
535 u8 fw_trips_index[IWL_MAX_DTS_TRIPS]; 535 u8 fw_trips_index[IWL_MAX_DTS_TRIPS];
536 struct thermal_zone_device *tzone; 536 struct thermal_zone_device *tzone;
537}; 537};
538
539/*
540 * iwl_mvm_cooling_device
541 * @cur_state: current state in milliwatts
542 * @cdev: struct thermal cooling device
543 */
544struct iwl_mvm_cooling_device {
545 u32 cur_state;
546 struct thermal_cooling_device *cdev;
547};
538#endif 548#endif
539 549
540#define IWL_MVM_NUM_LAST_FRAMES_UCODE_RATES 8 550#define IWL_MVM_NUM_LAST_FRAMES_UCODE_RATES 8
@@ -819,6 +829,7 @@ struct iwl_mvm {
819 struct iwl_mvm_tt_mgmt thermal_throttle; 829 struct iwl_mvm_tt_mgmt thermal_throttle;
820#ifdef CONFIG_THERMAL 830#ifdef CONFIG_THERMAL
821 struct iwl_mvm_thermal_device tz_device; 831 struct iwl_mvm_thermal_device tz_device;
832 struct iwl_mvm_cooling_device cooling_dev;
822#endif 833#endif
823 834
824 s32 temperature; /* Celsius */ 835 s32 temperature; /* Celsius */
@@ -1068,6 +1079,12 @@ static inline bool iwl_mvm_is_tt_in_fw(struct iwl_mvm *mvm)
1068#endif /* CONFIG_THERMAL */ 1079#endif /* CONFIG_THERMAL */
1069} 1080}
1070 1081
1082static inline bool iwl_mvm_is_ctdp_supported(struct iwl_mvm *mvm)
1083{
1084 return fw_has_capa(&mvm->fw->ucode_capa,
1085 IWL_UCODE_TLV_CAPA_CTDP_SUPPORT);
1086}
1087
1071extern const u8 iwl_mvm_ac_to_tx_fifo[]; 1088extern const u8 iwl_mvm_ac_to_tx_fifo[];
1072 1089
1073struct iwl_rate_info { 1090struct iwl_rate_info {
@@ -1544,6 +1561,8 @@ void iwl_mvm_set_hw_ctkill_state(struct iwl_mvm *mvm, bool state);
1544int iwl_mvm_get_temp(struct iwl_mvm *mvm, s32 *temp); 1561int iwl_mvm_get_temp(struct iwl_mvm *mvm, s32 *temp);
1545void iwl_mvm_ct_kill_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb); 1562void iwl_mvm_ct_kill_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb);
1546int iwl_mvm_send_temp_report_ths_cmd(struct iwl_mvm *mvm); 1563int iwl_mvm_send_temp_report_ths_cmd(struct iwl_mvm *mvm);
1564int iwl_mvm_cooling_device_register(struct iwl_mvm *mvm);
1565int iwl_mvm_ctdp_command(struct iwl_mvm *mvm, u32 op, u32 budget);
1547 1566
1548/* Location Aware Regulatory */ 1567/* Location Aware Regulatory */
1549struct iwl_mcc_update_resp * 1568struct iwl_mcc_update_resp *
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
index a7acadd446c4..ec3604678a56 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
@@ -389,6 +389,7 @@ static const struct iwl_hcmd_names iwl_mvm_legacy_names[] = {
389 */ 389 */
390static const struct iwl_hcmd_names iwl_mvm_phy_names[] = { 390static const struct iwl_hcmd_names iwl_mvm_phy_names[] = {
391 HCMD_NAME(CMD_DTS_MEASUREMENT_TRIGGER_WIDE), 391 HCMD_NAME(CMD_DTS_MEASUREMENT_TRIGGER_WIDE),
392 HCMD_NAME(CTDP_CONFIG_CMD),
392 HCMD_NAME(TEMP_REPORTING_THRESHOLDS_CMD), 393 HCMD_NAME(TEMP_REPORTING_THRESHOLDS_CMD),
393 HCMD_NAME(CT_KILL_NOTIFICATION), 394 HCMD_NAME(CT_KILL_NOTIFICATION),
394 HCMD_NAME(DTS_MEASUREMENT_NOTIF_WIDE), 395 HCMD_NAME(DTS_MEASUREMENT_NOTIF_WIDE),
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tt.c b/drivers/net/wireless/intel/iwlwifi/mvm/tt.c
index 466d169b0e62..999bcb898be8 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tt.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tt.c
@@ -706,6 +706,139 @@ static void iwl_mvm_thermal_zone_register(struct iwl_mvm *mvm)
706 mvm->tz_device.temp_trips[i] = S16_MIN; 706 mvm->tz_device.temp_trips[i] = S16_MIN;
707} 707}
708 708
709static const u32 iwl_mvm_cdev_budgets[] = {
710 2000, /* cooling state 0 */
711 1800, /* cooling state 1 */
712 1600, /* cooling state 2 */
713 1400, /* cooling state 3 */
714 1200, /* cooling state 4 */
715 1000, /* cooling state 5 */
716 900, /* cooling state 6 */
717 800, /* cooling state 7 */
718 700, /* cooling state 8 */
719 650, /* cooling state 9 */
720 600, /* cooling state 10 */
721 550, /* cooling state 11 */
722 500, /* cooling state 12 */
723 450, /* cooling state 13 */
724 400, /* cooling state 14 */
725 350, /* cooling state 15 */
726 300, /* cooling state 16 */
727 250, /* cooling state 17 */
728 200, /* cooling state 18 */
729 150, /* cooling state 19 */
730};
731
732int iwl_mvm_ctdp_command(struct iwl_mvm *mvm, u32 op, u32 budget)
733{
734 struct iwl_mvm_ctdp_cmd cmd = {
735 .operation = cpu_to_le32(op),
736 .budget = cpu_to_le32(budget),
737 .window_size = 0,
738 };
739 int ret;
740 u32 status;
741
742 lockdep_assert_held(&mvm->mutex);
743
744 ret = iwl_mvm_send_cmd_pdu_status(mvm, WIDE_ID(PHY_OPS_GROUP,
745 CTDP_CONFIG_CMD),
746 sizeof(cmd), &cmd, &status);
747
748 if (ret) {
749 IWL_ERR(mvm, "cTDP command failed (err=%d)\n", ret);
750 return ret;
751 }
752
753 if (op == CTDP_CMD_OPERATION_START)
754 mvm->cooling_dev.cur_state = budget;
755
756 else if (op == CTDP_CMD_OPERATION_REPORT)
757 IWL_DEBUG_TEMP(mvm, "cTDP avg energy in mWatt = %d\n", status);
758
759 return 0;
760}
761
762static int iwl_mvm_tcool_get_max_state(struct thermal_cooling_device *cdev,
763 unsigned long *state)
764{
765 *state = ARRAY_SIZE(iwl_mvm_cdev_budgets) - 1;
766
767 return 0;
768}
769
770static int iwl_mvm_tcool_get_cur_state(struct thermal_cooling_device *cdev,
771 unsigned long *state)
772{
773 struct iwl_mvm *mvm = (struct iwl_mvm *)(cdev->devdata);
774
775 if (test_bit(IWL_MVM_STATUS_IN_D0I3, &mvm->status))
776 return -EBUSY;
777
778 *state = mvm->cooling_dev.cur_state;
779 return 0;
780}
781
782static int iwl_mvm_tcool_set_cur_state(struct thermal_cooling_device *cdev,
783 unsigned long new_state)
784{
785 struct iwl_mvm *mvm = (struct iwl_mvm *)(cdev->devdata);
786 int ret;
787
788 if (!mvm->ucode_loaded || !(mvm->cur_ucode == IWL_UCODE_REGULAR))
789 return -EIO;
790
791 if (test_bit(IWL_MVM_STATUS_IN_D0I3, &mvm->status))
792 return -EBUSY;
793
794 mutex_lock(&mvm->mutex);
795
796 if (new_state >= ARRAY_SIZE(iwl_mvm_cdev_budgets)) {
797 ret = -EINVAL;
798 goto unlock;
799 }
800
801 ret = iwl_mvm_ctdp_command(mvm, CTDP_CMD_OPERATION_START,
802 iwl_mvm_cdev_budgets[new_state]);
803
804unlock:
805 mutex_unlock(&mvm->mutex);
806 return ret;
807}
808
809static struct thermal_cooling_device_ops tcooling_ops = {
810 .get_max_state = iwl_mvm_tcool_get_max_state,
811 .get_cur_state = iwl_mvm_tcool_get_cur_state,
812 .set_cur_state = iwl_mvm_tcool_set_cur_state,
813};
814
815int iwl_mvm_cooling_device_register(struct iwl_mvm *mvm)
816{
817 char name[] = "iwlwifi";
818
819 if (!iwl_mvm_is_ctdp_supported(mvm)) {
820 mvm->cooling_dev.cdev = NULL;
821
822 return 0;
823 }
824
825 BUILD_BUG_ON(ARRAY_SIZE(name) >= THERMAL_NAME_LENGTH);
826
827 mvm->cooling_dev.cdev =
828 thermal_cooling_device_register(name,
829 mvm,
830 &tcooling_ops);
831
832 if (IS_ERR(mvm->cooling_dev.cdev)) {
833 IWL_DEBUG_TEMP(mvm,
834 "Failed to register to cooling device (err = %ld)\n",
835 PTR_ERR(mvm->cooling_dev.cdev));
836 return PTR_ERR(mvm->cooling_dev.cdev);
837 }
838
839 return 0;
840}
841
709static void iwl_mvm_thermal_zone_unregister(struct iwl_mvm *mvm) 842static void iwl_mvm_thermal_zone_unregister(struct iwl_mvm *mvm)
710{ 843{
711 if (!iwl_mvm_is_tt_in_fw(mvm)) 844 if (!iwl_mvm_is_tt_in_fw(mvm))
@@ -717,6 +850,18 @@ static void iwl_mvm_thermal_zone_unregister(struct iwl_mvm *mvm)
717 mvm->tz_device.tzone = NULL; 850 mvm->tz_device.tzone = NULL;
718 } 851 }
719} 852}
853
854static void iwl_mvm_cooling_device_unregister(struct iwl_mvm *mvm)
855{
856 if (!iwl_mvm_is_ctdp_supported(mvm))
857 return;
858
859 if (mvm->cooling_dev.cdev) {
860 IWL_DEBUG_TEMP(mvm, "Cooling device unregister\n");
861 thermal_cooling_device_unregister(mvm->cooling_dev.cdev);
862 mvm->cooling_dev.cdev = NULL;
863 }
864}
720#endif /* CONFIG_THERMAL */ 865#endif /* CONFIG_THERMAL */
721 866
722void iwl_mvm_thermal_initialize(struct iwl_mvm *mvm, u32 min_backoff) 867void iwl_mvm_thermal_initialize(struct iwl_mvm *mvm, u32 min_backoff)
@@ -736,6 +881,7 @@ void iwl_mvm_thermal_initialize(struct iwl_mvm *mvm, u32 min_backoff)
736 INIT_DELAYED_WORK(&tt->ct_kill_exit, check_exit_ctkill); 881 INIT_DELAYED_WORK(&tt->ct_kill_exit, check_exit_ctkill);
737 882
738#ifdef CONFIG_THERMAL 883#ifdef CONFIG_THERMAL
884 iwl_mvm_cooling_device_register(mvm);
739 iwl_mvm_thermal_zone_register(mvm); 885 iwl_mvm_thermal_zone_register(mvm);
740#endif 886#endif
741} 887}
@@ -746,6 +892,7 @@ void iwl_mvm_thermal_exit(struct iwl_mvm *mvm)
746 IWL_DEBUG_TEMP(mvm, "Exit Thermal Throttling\n"); 892 IWL_DEBUG_TEMP(mvm, "Exit Thermal Throttling\n");
747 893
748#ifdef CONFIG_THERMAL 894#ifdef CONFIG_THERMAL
895 iwl_mvm_cooling_device_unregister(mvm);
749 iwl_mvm_thermal_zone_unregister(mvm); 896 iwl_mvm_thermal_zone_unregister(mvm);
750#endif 897#endif
751} 898}