1515
1616#define DRV_NAME "proc_thermal_pci"
1717
18+ static bool use_msi ;
19+ module_param (use_msi , bool , 0644 );
20+ MODULE_PARM_DESC (use_msi ,
21+ "Use PCI MSI based interrupts for processor thermal device." );
22+
1823struct proc_thermal_pci {
1924 struct pci_dev * pdev ;
2025 struct proc_thermal_device * proc_priv ;
@@ -117,20 +122,44 @@ static void pkg_thermal_schedule_work(struct delayed_work *work)
117122 schedule_delayed_work (work , ms );
118123}
119124
125+ static irqreturn_t proc_thermal_irq_thread_handler (int irq , void * devid )
126+ {
127+ struct proc_thermal_pci * pci_info = devid ;
128+
129+ proc_thermal_wt_intr_callback (pci_info -> pdev , pci_info -> proc_priv );
130+
131+ return IRQ_HANDLED ;
132+ }
133+
120134static irqreturn_t proc_thermal_irq_handler (int irq , void * devid )
121135{
122136 struct proc_thermal_pci * pci_info = devid ;
137+ struct proc_thermal_device * proc_priv ;
138+ int ret = IRQ_HANDLED ;
123139 u32 status ;
124140
141+ proc_priv = pci_info -> proc_priv ;
142+
143+ if (proc_priv -> mmio_feature_mask & PROC_THERMAL_FEATURE_WT_HINT ) {
144+ if (proc_thermal_check_wt_intr (pci_info -> proc_priv ))
145+ ret = IRQ_WAKE_THREAD ;
146+ }
147+
148+ /*
149+ * Since now there are two sources of interrupts: one from thermal threshold
150+ * and another from workload hint, add a check if there was really a threshold
151+ * interrupt before scheduling work function for thermal threshold.
152+ */
125153 proc_thermal_mmio_read (pci_info , PROC_THERMAL_MMIO_INT_STATUS_0 , & status );
154+ if (status ) {
155+ /* Disable enable interrupt flag */
156+ proc_thermal_mmio_write (pci_info , PROC_THERMAL_MMIO_INT_ENABLE_0 , 0 );
157+ pkg_thermal_schedule_work (& pci_info -> work );
158+ }
126159
127- /* Disable enable interrupt flag */
128- proc_thermal_mmio_write (pci_info , PROC_THERMAL_MMIO_INT_ENABLE_0 , 0 );
129160 pci_write_config_byte (pci_info -> pdev , 0xdc , 0x01 );
130161
131- pkg_thermal_schedule_work (& pci_info -> work );
132-
133- return IRQ_HANDLED ;
162+ return ret ;
134163}
135164
136165static int sys_get_curr_temp (struct thermal_zone_device * tzd , int * temp )
@@ -203,6 +232,7 @@ static int proc_thermal_pci_probe(struct pci_dev *pdev, const struct pci_device_
203232 struct proc_thermal_device * proc_priv ;
204233 struct proc_thermal_pci * pci_info ;
205234 int irq_flag = 0 , irq , ret ;
235+ bool msi_irq = false;
206236
207237 proc_priv = devm_kzalloc (& pdev -> dev , sizeof (* proc_priv ), GFP_KERNEL );
208238 if (!proc_priv )
@@ -248,18 +278,23 @@ static int proc_thermal_pci_probe(struct pci_dev *pdev, const struct pci_device_
248278 goto err_ret_mmio ;
249279 }
250280
251- /* request and enable interrupt */
252- ret = pci_alloc_irq_vectors (pdev , 1 , 1 , PCI_IRQ_ALL_TYPES );
253- if (ret < 0 ) {
254- dev_err (& pdev -> dev , "Failed to allocate vectors!\n" );
255- goto err_ret_tzone ;
256- }
257- if (!pdev -> msi_enabled && !pdev -> msix_enabled )
281+ if (use_msi && (pdev -> msi_enabled || pdev -> msix_enabled )) {
282+ /* request and enable interrupt */
283+ ret = pci_alloc_irq_vectors (pdev , 1 , 1 , PCI_IRQ_ALL_TYPES );
284+ if (ret < 0 ) {
285+ dev_err (& pdev -> dev , "Failed to allocate vectors!\n" );
286+ goto err_ret_tzone ;
287+ }
288+
289+ irq = pci_irq_vector (pdev , 0 );
290+ msi_irq = true;
291+ } else {
258292 irq_flag = IRQF_SHARED ;
293+ irq = pdev -> irq ;
294+ }
259295
260- irq = pci_irq_vector (pdev , 0 );
261296 ret = devm_request_threaded_irq (& pdev -> dev , irq ,
262- proc_thermal_irq_handler , NULL ,
297+ proc_thermal_irq_handler , proc_thermal_irq_thread_handler ,
263298 irq_flag , KBUILD_MODNAME , pci_info );
264299 if (ret ) {
265300 dev_err (& pdev -> dev , "Request IRQ %d failed\n" , pdev -> irq );
@@ -273,7 +308,8 @@ static int proc_thermal_pci_probe(struct pci_dev *pdev, const struct pci_device_
273308 return 0 ;
274309
275310err_free_vectors :
276- pci_free_irq_vectors (pdev );
311+ if (msi_irq )
312+ pci_free_irq_vectors (pdev );
277313err_ret_tzone :
278314 thermal_zone_device_unregister (pci_info -> tzone );
279315err_ret_mmio :
@@ -350,9 +386,15 @@ static SIMPLE_DEV_PM_OPS(proc_thermal_pci_pm, proc_thermal_pci_suspend,
350386 proc_thermal_pci_resume ) ;
351387
352388static const struct pci_device_id proc_thermal_pci_ids [] = {
353- { PCI_DEVICE_DATA (INTEL , ADL_THERMAL , PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_MBOX ) },
354- { 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 ) },
355- { PCI_DEVICE_DATA (INTEL , RPL_THERMAL , PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_MBOX ) },
389+ { PCI_DEVICE_DATA (INTEL , ADL_THERMAL , PROC_THERMAL_FEATURE_RAPL |
390+ PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_WT_REQ ) },
391+ { PCI_DEVICE_DATA (INTEL , MTLP_THERMAL , PROC_THERMAL_FEATURE_RAPL |
392+ PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_DLVR |
393+ PROC_THERMAL_FEATURE_WT_HINT ) },
394+ { PCI_DEVICE_DATA (INTEL , ARL_S_THERMAL , PROC_THERMAL_FEATURE_RAPL |
395+ PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_DLVR | PROC_THERMAL_FEATURE_WT_HINT ) },
396+ { PCI_DEVICE_DATA (INTEL , RPL_THERMAL , PROC_THERMAL_FEATURE_RAPL |
397+ PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_WT_REQ ) },
356398 { },
357399};
358400
@@ -368,6 +410,8 @@ static struct pci_driver proc_thermal_pci_driver = {
368410
369411module_pci_driver (proc_thermal_pci_driver );
370412
413+ MODULE_IMPORT_NS (INT340X_THERMAL );
414+
371415MODULE_AUTHOR ("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>" );
372416MODULE_DESCRIPTION ("Processor Thermal Reporting Device Driver" );
373417MODULE_LICENSE ("GPL v2" );
0 commit comments