Loading Documentation/driver-api/thermal/intel_dptf.rst +54 −0 Original line number Diff line number Diff line Loading @@ -315,3 +315,57 @@ DPTF Fan Control ---------------------------------------- Refer to Documentation/admin-guide/acpi/fan_performance_states.rst Workload Type Hints ---------------------------------------- The firmware in Meteor Lake processor generation is capable of identifying workload type and passing hints regarding it to the OS. A special sysfs interface is provided to allow user space to obtain workload type hints from the firmware and control the rate at which they are provided. User space can poll attribute "workload_type_index" for the current hint or can receive a notification whenever the value of this attribute is updated. file:`/sys/bus/pci/devices/0000:00:04.0/workload_hint/` Segment 0, bus 0, device 4, function 0 is reserved for the processor thermal device on all Intel client processors. So, the above path doesn't change based on the processor generation. ``workload_hint_enable`` (RW) Enable firmware to send workload type hints to user space. ``notification_delay_ms`` (RW) Minimum delay in milliseconds before firmware will notify OS. This is for the rate control of notifications. This delay is between changing the workload type prediction in the firmware and notifying the OS about the change. The default delay is 1024 ms. The delay of 0 is invalid. The delay is rounded up to the nearest power of 2 to simplify firmware programming of the delay value. The read of notification_delay_ms attribute shows the effective value used. ``workload_type_index`` (RO) Predicted workload type index. User space can get notification of change via existing sysfs attribute change notification mechanism. The supported index values and their meaning for the Meteor Lake processor generation are as follows: 0 - Idle: System performs no tasks, power and idle residency are consistently low for long periods of time. 1 – Battery Life: Power is relatively low, but the processor may still be actively performing a task, such as video playback for a long period of time. 2 – Sustained: Power level that is relatively high for a long period of time, with very few to no periods of idleness, which will eventually exhaust RAPL Power Limit 1 and 2. 3 – Bursty: Consumes a relatively constant average amount of power, but periods of relative idleness are interrupted by bursts of activity. The bursts are relatively short and the periods of relative idleness between them typically prevent RAPL Power Limit 1 from being exhausted. 4 – Unknown: Can't classify. drivers/thermal/intel/int340x_thermal/Makefile +2 −0 Original line number Diff line number Diff line Loading @@ -10,5 +10,7 @@ obj-$(CONFIG_INT340X_THERMAL) += processor_thermal_device_pci.o obj-$(CONFIG_PROC_THERMAL_MMIO_RAPL) += processor_thermal_rapl.o obj-$(CONFIG_INT340X_THERMAL) += processor_thermal_rfim.o obj-$(CONFIG_INT340X_THERMAL) += processor_thermal_mbox.o obj-$(CONFIG_INT340X_THERMAL) += processor_thermal_wt_req.o obj-$(CONFIG_INT340X_THERMAL) += processor_thermal_wt_hint.o obj-$(CONFIG_INT3406_THERMAL) += int3406_thermal.o obj-$(CONFIG_ACPI_THERMAL_REL) += acpi_thermal_rel.o drivers/thermal/intel/int340x_thermal/processor_thermal_device.c +13 −4 Original line number Diff line number Diff line Loading @@ -346,12 +346,18 @@ int proc_thermal_mmio_add(struct pci_dev *pdev, } } if (feature_mask & PROC_THERMAL_FEATURE_MBOX) { ret = proc_thermal_mbox_add(pdev, proc_priv); if (feature_mask & PROC_THERMAL_FEATURE_WT_REQ) { ret = proc_thermal_wt_req_add(pdev, proc_priv); if (ret) { dev_err(&pdev->dev, "failed to add MBOX interface\n"); goto err_rem_rfim; } } else if (feature_mask & PROC_THERMAL_FEATURE_WT_HINT) { ret = proc_thermal_wt_hint_add(pdev, proc_priv); if (ret) { dev_err(&pdev->dev, "failed to add WT Hint\n"); goto err_rem_rfim; } } return 0; Loading @@ -374,12 +380,15 @@ void proc_thermal_mmio_remove(struct pci_dev *pdev, struct proc_thermal_device * proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_DVFS) proc_thermal_rfim_remove(pdev); if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_MBOX) proc_thermal_mbox_remove(pdev); if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_WT_REQ) proc_thermal_wt_req_remove(pdev); else if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_WT_HINT) proc_thermal_wt_hint_remove(pdev); } EXPORT_SYMBOL_GPL(proc_thermal_mmio_remove); MODULE_IMPORT_NS(INTEL_TCC); MODULE_IMPORT_NS(INT340X_THERMAL); MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>"); MODULE_DESCRIPTION("Processor Thermal Reporting Device Driver"); MODULE_LICENSE("GPL v2"); drivers/thermal/intel/int340x_thermal/processor_thermal_device.h +19 −3 Original line number Diff line number Diff line Loading @@ -10,6 +10,7 @@ #include <linux/intel_rapl.h> #define PCI_DEVICE_ID_INTEL_ADL_THERMAL 0x461d #define PCI_DEVICE_ID_INTEL_ARL_S_THERMAL 0xAD03 #define PCI_DEVICE_ID_INTEL_BDW_THERMAL 0x1603 #define PCI_DEVICE_ID_INTEL_BSW_THERMAL 0x22DC Loading Loading @@ -59,8 +60,9 @@ struct rapl_mmio_regs { #define PROC_THERMAL_FEATURE_RAPL 0x01 #define PROC_THERMAL_FEATURE_FIVR 0x02 #define PROC_THERMAL_FEATURE_DVFS 0x04 #define PROC_THERMAL_FEATURE_MBOX 0x08 #define PROC_THERMAL_FEATURE_WT_REQ 0x08 #define PROC_THERMAL_FEATURE_DLVR 0x10 #define PROC_THERMAL_FEATURE_WT_HINT 0x20 #if IS_ENABLED(CONFIG_PROC_THERMAL_MMIO_RAPL) int proc_thermal_rapl_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv); Loading @@ -80,13 +82,27 @@ static void __maybe_unused proc_thermal_rapl_remove(void) int proc_thermal_rfim_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv); void proc_thermal_rfim_remove(struct pci_dev *pdev); int proc_thermal_mbox_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv); void proc_thermal_mbox_remove(struct pci_dev *pdev); int proc_thermal_wt_req_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv); void proc_thermal_wt_req_remove(struct pci_dev *pdev); #define MBOX_CMD_WORKLOAD_TYPE_READ 0x0E #define MBOX_CMD_WORKLOAD_TYPE_WRITE 0x0F #define MBOX_DATA_BIT_AC_DC 30 #define MBOX_DATA_BIT_VALID 31 int processor_thermal_send_mbox_read_cmd(struct pci_dev *pdev, u16 id, u64 *resp); int processor_thermal_send_mbox_write_cmd(struct pci_dev *pdev, u16 id, u32 data); int processor_thermal_mbox_interrupt_config(struct pci_dev *pdev, bool enable, int enable_bit, int time_window); int proc_thermal_add(struct device *dev, struct proc_thermal_device *priv); void proc_thermal_remove(struct proc_thermal_device *proc_priv); int proc_thermal_wt_hint_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv); void proc_thermal_wt_hint_remove(struct pci_dev *pdev); void proc_thermal_wt_intr_callback(struct pci_dev *pdev, struct proc_thermal_device *proc_priv); bool proc_thermal_check_wt_intr(struct proc_thermal_device *proc_priv); int proc_thermal_suspend(struct device *dev); int proc_thermal_resume(struct device *dev); int proc_thermal_mmio_add(struct pci_dev *pdev, Loading drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c +62 −18 Original line number Diff line number Diff line Loading @@ -15,6 +15,11 @@ #define DRV_NAME "proc_thermal_pci" static bool use_msi; module_param(use_msi, bool, 0644); MODULE_PARM_DESC(use_msi, "Use PCI MSI based interrupts for processor thermal device."); struct proc_thermal_pci { struct pci_dev *pdev; struct proc_thermal_device *proc_priv; Loading Loading @@ -117,20 +122,44 @@ static void pkg_thermal_schedule_work(struct delayed_work *work) schedule_delayed_work(work, ms); } static irqreturn_t proc_thermal_irq_thread_handler(int irq, void *devid) { struct proc_thermal_pci *pci_info = devid; proc_thermal_wt_intr_callback(pci_info->pdev, pci_info->proc_priv); return IRQ_HANDLED; } static irqreturn_t proc_thermal_irq_handler(int irq, void *devid) { struct proc_thermal_pci *pci_info = devid; struct proc_thermal_device *proc_priv; int ret = IRQ_HANDLED; u32 status; proc_thermal_mmio_read(pci_info, PROC_THERMAL_MMIO_INT_STATUS_0, &status); proc_priv = pci_info->proc_priv; if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_WT_HINT) { if (proc_thermal_check_wt_intr(pci_info->proc_priv)) ret = IRQ_WAKE_THREAD; } /* * Since now there are two sources of interrupts: one from thermal threshold * and another from workload hint, add a check if there was really a threshold * interrupt before scheduling work function for thermal threshold. */ proc_thermal_mmio_read(pci_info, PROC_THERMAL_MMIO_INT_STATUS_0, &status); if (status) { /* Disable enable interrupt flag */ proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_INT_ENABLE_0, 0); pci_write_config_byte(pci_info->pdev, 0xdc, 0x01); pkg_thermal_schedule_work(&pci_info->work); } return IRQ_HANDLED; pci_write_config_byte(pci_info->pdev, 0xdc, 0x01); return ret; } static int sys_get_curr_temp(struct thermal_zone_device *tzd, int *temp) Loading Loading @@ -203,6 +232,7 @@ static int proc_thermal_pci_probe(struct pci_dev *pdev, const struct pci_device_ struct proc_thermal_device *proc_priv; struct proc_thermal_pci *pci_info; int irq_flag = 0, irq, ret; bool msi_irq = false; proc_priv = devm_kzalloc(&pdev->dev, sizeof(*proc_priv), GFP_KERNEL); if (!proc_priv) Loading Loading @@ -248,18 +278,23 @@ static int proc_thermal_pci_probe(struct pci_dev *pdev, const struct pci_device_ goto err_ret_mmio; } if (use_msi && (pdev->msi_enabled || pdev->msix_enabled)) { /* request and enable interrupt */ ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES); if (ret < 0) { dev_err(&pdev->dev, "Failed to allocate vectors!\n"); goto err_ret_tzone; } if (!pdev->msi_enabled && !pdev->msix_enabled) irq_flag = IRQF_SHARED; irq = pci_irq_vector(pdev, 0); msi_irq = true; } else { irq_flag = IRQF_SHARED; irq = pdev->irq; } ret = devm_request_threaded_irq(&pdev->dev, irq, proc_thermal_irq_handler, NULL, proc_thermal_irq_handler, proc_thermal_irq_thread_handler, irq_flag, KBUILD_MODNAME, pci_info); if (ret) { dev_err(&pdev->dev, "Request IRQ %d failed\n", pdev->irq); Loading @@ -273,6 +308,7 @@ static int proc_thermal_pci_probe(struct pci_dev *pdev, const struct pci_device_ return 0; err_free_vectors: if (msi_irq) pci_free_irq_vectors(pdev); err_ret_tzone: thermal_zone_device_unregister(pci_info->tzone); Loading Loading @@ -350,9 +386,15 @@ static SIMPLE_DEV_PM_OPS(proc_thermal_pci_pm, proc_thermal_pci_suspend, proc_thermal_pci_resume); static const struct pci_device_id proc_thermal_pci_ids[] = { { PCI_DEVICE_DATA(INTEL, ADL_THERMAL, PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_MBOX) }, { PCI_DEVICE_DATA(INTEL, MTLP_THERMAL, PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_MBOX | PROC_THERMAL_FEATURE_DLVR) }, { PCI_DEVICE_DATA(INTEL, RPL_THERMAL, PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_MBOX) }, { PCI_DEVICE_DATA(INTEL, ADL_THERMAL, PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_WT_REQ) }, { PCI_DEVICE_DATA(INTEL, MTLP_THERMAL, PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_DLVR | PROC_THERMAL_FEATURE_WT_HINT) }, { PCI_DEVICE_DATA(INTEL, ARL_S_THERMAL, PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_DLVR | PROC_THERMAL_FEATURE_WT_HINT) }, { PCI_DEVICE_DATA(INTEL, RPL_THERMAL, PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_WT_REQ) }, { }, }; Loading @@ -368,6 +410,8 @@ static struct pci_driver proc_thermal_pci_driver = { module_pci_driver(proc_thermal_pci_driver); MODULE_IMPORT_NS(INT340X_THERMAL); MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>"); MODULE_DESCRIPTION("Processor Thermal Reporting Device Driver"); MODULE_LICENSE("GPL v2"); Loading
Documentation/driver-api/thermal/intel_dptf.rst +54 −0 Original line number Diff line number Diff line Loading @@ -315,3 +315,57 @@ DPTF Fan Control ---------------------------------------- Refer to Documentation/admin-guide/acpi/fan_performance_states.rst Workload Type Hints ---------------------------------------- The firmware in Meteor Lake processor generation is capable of identifying workload type and passing hints regarding it to the OS. A special sysfs interface is provided to allow user space to obtain workload type hints from the firmware and control the rate at which they are provided. User space can poll attribute "workload_type_index" for the current hint or can receive a notification whenever the value of this attribute is updated. file:`/sys/bus/pci/devices/0000:00:04.0/workload_hint/` Segment 0, bus 0, device 4, function 0 is reserved for the processor thermal device on all Intel client processors. So, the above path doesn't change based on the processor generation. ``workload_hint_enable`` (RW) Enable firmware to send workload type hints to user space. ``notification_delay_ms`` (RW) Minimum delay in milliseconds before firmware will notify OS. This is for the rate control of notifications. This delay is between changing the workload type prediction in the firmware and notifying the OS about the change. The default delay is 1024 ms. The delay of 0 is invalid. The delay is rounded up to the nearest power of 2 to simplify firmware programming of the delay value. The read of notification_delay_ms attribute shows the effective value used. ``workload_type_index`` (RO) Predicted workload type index. User space can get notification of change via existing sysfs attribute change notification mechanism. The supported index values and their meaning for the Meteor Lake processor generation are as follows: 0 - Idle: System performs no tasks, power and idle residency are consistently low for long periods of time. 1 – Battery Life: Power is relatively low, but the processor may still be actively performing a task, such as video playback for a long period of time. 2 – Sustained: Power level that is relatively high for a long period of time, with very few to no periods of idleness, which will eventually exhaust RAPL Power Limit 1 and 2. 3 – Bursty: Consumes a relatively constant average amount of power, but periods of relative idleness are interrupted by bursts of activity. The bursts are relatively short and the periods of relative idleness between them typically prevent RAPL Power Limit 1 from being exhausted. 4 – Unknown: Can't classify.
drivers/thermal/intel/int340x_thermal/Makefile +2 −0 Original line number Diff line number Diff line Loading @@ -10,5 +10,7 @@ obj-$(CONFIG_INT340X_THERMAL) += processor_thermal_device_pci.o obj-$(CONFIG_PROC_THERMAL_MMIO_RAPL) += processor_thermal_rapl.o obj-$(CONFIG_INT340X_THERMAL) += processor_thermal_rfim.o obj-$(CONFIG_INT340X_THERMAL) += processor_thermal_mbox.o obj-$(CONFIG_INT340X_THERMAL) += processor_thermal_wt_req.o obj-$(CONFIG_INT340X_THERMAL) += processor_thermal_wt_hint.o obj-$(CONFIG_INT3406_THERMAL) += int3406_thermal.o obj-$(CONFIG_ACPI_THERMAL_REL) += acpi_thermal_rel.o
drivers/thermal/intel/int340x_thermal/processor_thermal_device.c +13 −4 Original line number Diff line number Diff line Loading @@ -346,12 +346,18 @@ int proc_thermal_mmio_add(struct pci_dev *pdev, } } if (feature_mask & PROC_THERMAL_FEATURE_MBOX) { ret = proc_thermal_mbox_add(pdev, proc_priv); if (feature_mask & PROC_THERMAL_FEATURE_WT_REQ) { ret = proc_thermal_wt_req_add(pdev, proc_priv); if (ret) { dev_err(&pdev->dev, "failed to add MBOX interface\n"); goto err_rem_rfim; } } else if (feature_mask & PROC_THERMAL_FEATURE_WT_HINT) { ret = proc_thermal_wt_hint_add(pdev, proc_priv); if (ret) { dev_err(&pdev->dev, "failed to add WT Hint\n"); goto err_rem_rfim; } } return 0; Loading @@ -374,12 +380,15 @@ void proc_thermal_mmio_remove(struct pci_dev *pdev, struct proc_thermal_device * proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_DVFS) proc_thermal_rfim_remove(pdev); if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_MBOX) proc_thermal_mbox_remove(pdev); if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_WT_REQ) proc_thermal_wt_req_remove(pdev); else if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_WT_HINT) proc_thermal_wt_hint_remove(pdev); } EXPORT_SYMBOL_GPL(proc_thermal_mmio_remove); MODULE_IMPORT_NS(INTEL_TCC); MODULE_IMPORT_NS(INT340X_THERMAL); MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>"); MODULE_DESCRIPTION("Processor Thermal Reporting Device Driver"); MODULE_LICENSE("GPL v2");
drivers/thermal/intel/int340x_thermal/processor_thermal_device.h +19 −3 Original line number Diff line number Diff line Loading @@ -10,6 +10,7 @@ #include <linux/intel_rapl.h> #define PCI_DEVICE_ID_INTEL_ADL_THERMAL 0x461d #define PCI_DEVICE_ID_INTEL_ARL_S_THERMAL 0xAD03 #define PCI_DEVICE_ID_INTEL_BDW_THERMAL 0x1603 #define PCI_DEVICE_ID_INTEL_BSW_THERMAL 0x22DC Loading Loading @@ -59,8 +60,9 @@ struct rapl_mmio_regs { #define PROC_THERMAL_FEATURE_RAPL 0x01 #define PROC_THERMAL_FEATURE_FIVR 0x02 #define PROC_THERMAL_FEATURE_DVFS 0x04 #define PROC_THERMAL_FEATURE_MBOX 0x08 #define PROC_THERMAL_FEATURE_WT_REQ 0x08 #define PROC_THERMAL_FEATURE_DLVR 0x10 #define PROC_THERMAL_FEATURE_WT_HINT 0x20 #if IS_ENABLED(CONFIG_PROC_THERMAL_MMIO_RAPL) int proc_thermal_rapl_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv); Loading @@ -80,13 +82,27 @@ static void __maybe_unused proc_thermal_rapl_remove(void) int proc_thermal_rfim_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv); void proc_thermal_rfim_remove(struct pci_dev *pdev); int proc_thermal_mbox_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv); void proc_thermal_mbox_remove(struct pci_dev *pdev); int proc_thermal_wt_req_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv); void proc_thermal_wt_req_remove(struct pci_dev *pdev); #define MBOX_CMD_WORKLOAD_TYPE_READ 0x0E #define MBOX_CMD_WORKLOAD_TYPE_WRITE 0x0F #define MBOX_DATA_BIT_AC_DC 30 #define MBOX_DATA_BIT_VALID 31 int processor_thermal_send_mbox_read_cmd(struct pci_dev *pdev, u16 id, u64 *resp); int processor_thermal_send_mbox_write_cmd(struct pci_dev *pdev, u16 id, u32 data); int processor_thermal_mbox_interrupt_config(struct pci_dev *pdev, bool enable, int enable_bit, int time_window); int proc_thermal_add(struct device *dev, struct proc_thermal_device *priv); void proc_thermal_remove(struct proc_thermal_device *proc_priv); int proc_thermal_wt_hint_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv); void proc_thermal_wt_hint_remove(struct pci_dev *pdev); void proc_thermal_wt_intr_callback(struct pci_dev *pdev, struct proc_thermal_device *proc_priv); bool proc_thermal_check_wt_intr(struct proc_thermal_device *proc_priv); int proc_thermal_suspend(struct device *dev); int proc_thermal_resume(struct device *dev); int proc_thermal_mmio_add(struct pci_dev *pdev, Loading
drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c +62 −18 Original line number Diff line number Diff line Loading @@ -15,6 +15,11 @@ #define DRV_NAME "proc_thermal_pci" static bool use_msi; module_param(use_msi, bool, 0644); MODULE_PARM_DESC(use_msi, "Use PCI MSI based interrupts for processor thermal device."); struct proc_thermal_pci { struct pci_dev *pdev; struct proc_thermal_device *proc_priv; Loading Loading @@ -117,20 +122,44 @@ static void pkg_thermal_schedule_work(struct delayed_work *work) schedule_delayed_work(work, ms); } static irqreturn_t proc_thermal_irq_thread_handler(int irq, void *devid) { struct proc_thermal_pci *pci_info = devid; proc_thermal_wt_intr_callback(pci_info->pdev, pci_info->proc_priv); return IRQ_HANDLED; } static irqreturn_t proc_thermal_irq_handler(int irq, void *devid) { struct proc_thermal_pci *pci_info = devid; struct proc_thermal_device *proc_priv; int ret = IRQ_HANDLED; u32 status; proc_thermal_mmio_read(pci_info, PROC_THERMAL_MMIO_INT_STATUS_0, &status); proc_priv = pci_info->proc_priv; if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_WT_HINT) { if (proc_thermal_check_wt_intr(pci_info->proc_priv)) ret = IRQ_WAKE_THREAD; } /* * Since now there are two sources of interrupts: one from thermal threshold * and another from workload hint, add a check if there was really a threshold * interrupt before scheduling work function for thermal threshold. */ proc_thermal_mmio_read(pci_info, PROC_THERMAL_MMIO_INT_STATUS_0, &status); if (status) { /* Disable enable interrupt flag */ proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_INT_ENABLE_0, 0); pci_write_config_byte(pci_info->pdev, 0xdc, 0x01); pkg_thermal_schedule_work(&pci_info->work); } return IRQ_HANDLED; pci_write_config_byte(pci_info->pdev, 0xdc, 0x01); return ret; } static int sys_get_curr_temp(struct thermal_zone_device *tzd, int *temp) Loading Loading @@ -203,6 +232,7 @@ static int proc_thermal_pci_probe(struct pci_dev *pdev, const struct pci_device_ struct proc_thermal_device *proc_priv; struct proc_thermal_pci *pci_info; int irq_flag = 0, irq, ret; bool msi_irq = false; proc_priv = devm_kzalloc(&pdev->dev, sizeof(*proc_priv), GFP_KERNEL); if (!proc_priv) Loading Loading @@ -248,18 +278,23 @@ static int proc_thermal_pci_probe(struct pci_dev *pdev, const struct pci_device_ goto err_ret_mmio; } if (use_msi && (pdev->msi_enabled || pdev->msix_enabled)) { /* request and enable interrupt */ ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES); if (ret < 0) { dev_err(&pdev->dev, "Failed to allocate vectors!\n"); goto err_ret_tzone; } if (!pdev->msi_enabled && !pdev->msix_enabled) irq_flag = IRQF_SHARED; irq = pci_irq_vector(pdev, 0); msi_irq = true; } else { irq_flag = IRQF_SHARED; irq = pdev->irq; } ret = devm_request_threaded_irq(&pdev->dev, irq, proc_thermal_irq_handler, NULL, proc_thermal_irq_handler, proc_thermal_irq_thread_handler, irq_flag, KBUILD_MODNAME, pci_info); if (ret) { dev_err(&pdev->dev, "Request IRQ %d failed\n", pdev->irq); Loading @@ -273,6 +308,7 @@ static int proc_thermal_pci_probe(struct pci_dev *pdev, const struct pci_device_ return 0; err_free_vectors: if (msi_irq) pci_free_irq_vectors(pdev); err_ret_tzone: thermal_zone_device_unregister(pci_info->tzone); Loading Loading @@ -350,9 +386,15 @@ static SIMPLE_DEV_PM_OPS(proc_thermal_pci_pm, proc_thermal_pci_suspend, proc_thermal_pci_resume); static const struct pci_device_id proc_thermal_pci_ids[] = { { PCI_DEVICE_DATA(INTEL, ADL_THERMAL, PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_MBOX) }, { PCI_DEVICE_DATA(INTEL, MTLP_THERMAL, PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_MBOX | PROC_THERMAL_FEATURE_DLVR) }, { PCI_DEVICE_DATA(INTEL, RPL_THERMAL, PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_MBOX) }, { PCI_DEVICE_DATA(INTEL, ADL_THERMAL, PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_WT_REQ) }, { PCI_DEVICE_DATA(INTEL, MTLP_THERMAL, PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_DLVR | PROC_THERMAL_FEATURE_WT_HINT) }, { PCI_DEVICE_DATA(INTEL, ARL_S_THERMAL, PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_DLVR | PROC_THERMAL_FEATURE_WT_HINT) }, { PCI_DEVICE_DATA(INTEL, RPL_THERMAL, PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_WT_REQ) }, { }, }; Loading @@ -368,6 +410,8 @@ static struct pci_driver proc_thermal_pci_driver = { module_pci_driver(proc_thermal_pci_driver); MODULE_IMPORT_NS(INT340X_THERMAL); MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>"); MODULE_DESCRIPTION("Processor Thermal Reporting Device Driver"); MODULE_LICENSE("GPL v2");