These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / thermal / int340x_thermal / processor_thermal_device.c
index 5e8d8e9..ccc0ad0 100644 (file)
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/pci.h>
+#include <linux/interrupt.h>
 #include <linux/platform_device.h>
 #include <linux/acpi.h>
 #include <linux/thermal.h>
 #include "int340x_thermal_zone.h"
+#include "../intel_soc_dts_iosf.h"
 
 /* Broadwell-U/HSB thermal reporting device */
 #define PCI_DEVICE_ID_PROC_BDW_THERMAL 0x1603
 #define PCI_DEVICE_ID_PROC_HSB_THERMAL 0x0A03
 
+/* Skylake thermal reporting device */
+#define PCI_DEVICE_ID_PROC_SKL_THERMAL 0x1903
+
 /* Braswell thermal reporting device */
 #define PCI_DEVICE_ID_PROC_BSW_THERMAL 0x22DC
 
@@ -42,6 +47,7 @@ struct proc_thermal_device {
        struct acpi_device *adev;
        struct power_config power_limits[2];
        struct int34x_thermal_zone *int340x_zone;
+       struct intel_soc_dts_sensors *soc_dts;
 };
 
 enum proc_thermal_emum_mode_type {
@@ -139,7 +145,7 @@ static int get_tjmax(void)
        return -EINVAL;
 }
 
-static int read_temp_msr(unsigned long *temp)
+static int read_temp_msr(int *temp)
 {
        int cpu;
        u32 eax, edx;
@@ -171,7 +177,7 @@ err_ret:
 }
 
 static int proc_thermal_get_zone_temp(struct thermal_zone_device *zone,
-                                        unsigned long *temp)
+                                        int *temp)
 {
        int ret;
 
@@ -308,6 +314,18 @@ static int int3401_remove(struct platform_device *pdev)
        return 0;
 }
 
+static irqreturn_t proc_thermal_pci_msi_irq(int irq, void *devid)
+{
+       struct proc_thermal_device *proc_priv;
+       struct pci_dev *pdev = devid;
+
+       proc_priv = pci_get_drvdata(pdev);
+
+       intel_soc_dts_iosf_interrupt_handler(proc_priv->soc_dts);
+
+       return IRQ_HANDLED;
+}
+
 static int  proc_thermal_pci_probe(struct pci_dev *pdev,
                                   const struct pci_device_id *unused)
 {
@@ -334,18 +352,57 @@ static int  proc_thermal_pci_probe(struct pci_dev *pdev,
        pci_set_drvdata(pdev, proc_priv);
        proc_thermal_emum_mode = PROC_THERMAL_PCI;
 
+       if (pdev->device == PCI_DEVICE_ID_PROC_BSW_THERMAL) {
+               /*
+                * Enumerate additional DTS sensors available via IOSF.
+                * But we are not treating as a failure condition, if
+                * there are no aux DTSs enabled or fails. This driver
+                * already exposes sensors, which can be accessed via
+                * ACPI/MSR. So we don't want to fail for auxiliary DTSs.
+                */
+               proc_priv->soc_dts = intel_soc_dts_iosf_init(
+                                       INTEL_SOC_DTS_INTERRUPT_MSI, 2, 0);
+
+               if (proc_priv->soc_dts && pdev->irq) {
+                       ret = pci_enable_msi(pdev);
+                       if (!ret) {
+                               ret = request_threaded_irq(pdev->irq, NULL,
+                                               proc_thermal_pci_msi_irq,
+                                               IRQF_ONESHOT, "proc_thermal",
+                                               pdev);
+                               if (ret) {
+                                       intel_soc_dts_iosf_exit(
+                                                       proc_priv->soc_dts);
+                                       pci_disable_msi(pdev);
+                                       proc_priv->soc_dts = NULL;
+                               }
+                       }
+               } else
+                       dev_err(&pdev->dev, "No auxiliary DTSs enabled\n");
+       }
+
        return 0;
 }
 
 static void  proc_thermal_pci_remove(struct pci_dev *pdev)
 {
-       proc_thermal_remove(pci_get_drvdata(pdev));
+       struct proc_thermal_device *proc_priv = pci_get_drvdata(pdev);
+
+       if (proc_priv->soc_dts) {
+               intel_soc_dts_iosf_exit(proc_priv->soc_dts);
+               if (pdev->irq) {
+                       free_irq(pdev->irq, pdev);
+                       pci_disable_msi(pdev);
+               }
+       }
+       proc_thermal_remove(proc_priv);
        pci_disable_device(pdev);
 }
 
 static const struct pci_device_id proc_thermal_pci_ids[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_BDW_THERMAL)},
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_HSB_THERMAL)},
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_SKL_THERMAL)},
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_BSW_THERMAL)},
        { 0, },
 };