15
15
16
16
#define DRV_NAME "proc_thermal_pci"
17
17
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
+
18
23
struct proc_thermal_pci {
19
24
struct pci_dev * pdev ;
20
25
struct proc_thermal_device * proc_priv ;
@@ -117,20 +122,44 @@ static void pkg_thermal_schedule_work(struct delayed_work *work)
117
122
schedule_delayed_work (work , ms );
118
123
}
119
124
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
+
120
134
static irqreturn_t proc_thermal_irq_handler (int irq , void * devid )
121
135
{
122
136
struct proc_thermal_pci * pci_info = devid ;
137
+ struct proc_thermal_device * proc_priv ;
138
+ int ret = IRQ_HANDLED ;
123
139
u32 status ;
124
140
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
+ */
125
153
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
+ }
126
159
127
- /* Disable enable interrupt flag */
128
- proc_thermal_mmio_write (pci_info , PROC_THERMAL_MMIO_INT_ENABLE_0 , 0 );
129
160
pci_write_config_byte (pci_info -> pdev , 0xdc , 0x01 );
130
161
131
- pkg_thermal_schedule_work (& pci_info -> work );
132
-
133
- return IRQ_HANDLED ;
162
+ return ret ;
134
163
}
135
164
136
165
static 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_
203
232
struct proc_thermal_device * proc_priv ;
204
233
struct proc_thermal_pci * pci_info ;
205
234
int irq_flag = 0 , irq , ret ;
235
+ bool msi_irq = false;
206
236
207
237
proc_priv = devm_kzalloc (& pdev -> dev , sizeof (* proc_priv ), GFP_KERNEL );
208
238
if (!proc_priv )
@@ -248,18 +278,23 @@ static int proc_thermal_pci_probe(struct pci_dev *pdev, const struct pci_device_
248
278
goto err_ret_mmio ;
249
279
}
250
280
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 {
258
292
irq_flag = IRQF_SHARED ;
293
+ irq = pdev -> irq ;
294
+ }
259
295
260
- irq = pci_irq_vector (pdev , 0 );
261
296
ret = devm_request_threaded_irq (& pdev -> dev , irq ,
262
- proc_thermal_irq_handler , NULL ,
297
+ proc_thermal_irq_handler , proc_thermal_irq_thread_handler ,
263
298
irq_flag , KBUILD_MODNAME , pci_info );
264
299
if (ret ) {
265
300
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_
273
308
return 0 ;
274
309
275
310
err_free_vectors :
276
- pci_free_irq_vectors (pdev );
311
+ if (msi_irq )
312
+ pci_free_irq_vectors (pdev );
277
313
err_ret_tzone :
278
314
thermal_zone_device_unregister (pci_info -> tzone );
279
315
err_ret_mmio :
@@ -350,9 +386,15 @@ static SIMPLE_DEV_PM_OPS(proc_thermal_pci_pm, proc_thermal_pci_suspend,
350
386
proc_thermal_pci_resume ) ;
351
387
352
388
static 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 ) },
356
398
{ },
357
399
};
358
400
@@ -368,6 +410,8 @@ static struct pci_driver proc_thermal_pci_driver = {
368
410
369
411
module_pci_driver (proc_thermal_pci_driver );
370
412
413
+ MODULE_IMPORT_NS (INT340X_THERMAL );
414
+
371
415
MODULE_AUTHOR (
"Srinivas Pandruvada <[email protected] >" );
372
416
MODULE_DESCRIPTION ("Processor Thermal Reporting Device Driver" );
373
417
MODULE_LICENSE ("GPL v2" );
0 commit comments