3838
3939#include <linux/kernel.h>
4040#include <linux/module.h>
41+ #include <linux/debugfs.h>
4142#include <linux/pci.h>
4243#include "processor_thermal_device.h"
4344
@@ -49,14 +50,16 @@ struct mmio_reg {
4950};
5051
5152#define MAX_ATTR_GROUP_NAME_LEN 32
52- #define PTC_MAX_ATTRS 3
53+ #define PTC_MAX_ATTRS 4
5354
5455struct ptc_data {
5556 u32 offset ;
57+ struct pci_dev * pdev ;
5658 struct attribute_group ptc_attr_group ;
5759 struct attribute * ptc_attrs [PTC_MAX_ATTRS ];
5860 struct device_attribute temperature_target_attr ;
5961 struct device_attribute enable_attr ;
62+ struct device_attribute thermal_tolerance_attr ;
6063 char group_name [MAX_ATTR_GROUP_NAME_LEN ];
6164};
6265
@@ -78,6 +81,7 @@ static u32 ptc_offsets[PTC_MAX_INSTANCES] = {0x5B20, 0x5B28, 0x5B30};
7881static const char * const ptc_strings [] = {
7982 "temperature_target" ,
8083 "enable" ,
84+ "thermal_tolerance" ,
8185 NULL
8286};
8387
@@ -177,6 +181,8 @@ PTC_SHOW(temperature_target);
177181PTC_STORE (temperature_target );
178182PTC_SHOW (enable );
179183PTC_STORE (enable );
184+ PTC_SHOW (thermal_tolerance );
185+ PTC_STORE (thermal_tolerance );
180186
181187#define ptc_init_attribute (_name )\
182188 do {\
@@ -193,9 +199,11 @@ static int ptc_create_groups(struct pci_dev *pdev, int instance, struct ptc_data
193199
194200 ptc_init_attribute (temperature_target );
195201 ptc_init_attribute (enable );
202+ ptc_init_attribute (thermal_tolerance );
196203
197204 data -> ptc_attrs [index ++ ] = & data -> temperature_target_attr .attr ;
198205 data -> ptc_attrs [index ++ ] = & data -> enable_attr .attr ;
206+ data -> ptc_attrs [index ++ ] = & data -> thermal_tolerance_attr .attr ;
199207 data -> ptc_attrs [index ] = NULL ;
200208
201209 snprintf (data -> group_name , MAX_ATTR_GROUP_NAME_LEN ,
@@ -209,6 +217,63 @@ static int ptc_create_groups(struct pci_dev *pdev, int instance, struct ptc_data
209217}
210218
211219static struct ptc_data ptc_instance [PTC_MAX_INSTANCES ];
220+ static struct dentry * ptc_debugfs ;
221+
222+ #define PTC_TEMP_OVERRIDE_ENABLE_INDEX 4
223+ #define PTC_TEMP_OVERRIDE_INDEX 5
224+
225+ static ssize_t ptc_temperature_write (struct file * file , const char __user * data ,
226+ size_t count , loff_t * ppos )
227+ {
228+ struct ptc_data * ptc_instance = file -> private_data ;
229+ struct pci_dev * pdev = ptc_instance -> pdev ;
230+ char buf [32 ];
231+ ssize_t len ;
232+ u32 value ;
233+
234+ len = min (count , sizeof (buf ) - 1 );
235+ if (copy_from_user (buf , data , len ))
236+ return - EFAULT ;
237+
238+ buf [len ] = '\0' ;
239+ if (kstrtouint (buf , 0 , & value ))
240+ return - EINVAL ;
241+
242+ if (ptc_mmio_regs [PTC_TEMP_OVERRIDE_INDEX ].units )
243+ value /= ptc_mmio_regs [PTC_TEMP_OVERRIDE_INDEX ].units ;
244+
245+ if (value > ptc_mmio_regs [PTC_TEMP_OVERRIDE_INDEX ].mask )
246+ return - EINVAL ;
247+
248+ if (!value ) {
249+ ptc_mmio_write (pdev , ptc_instance -> offset , PTC_TEMP_OVERRIDE_ENABLE_INDEX , 0 );
250+ } else {
251+ ptc_mmio_write (pdev , ptc_instance -> offset , PTC_TEMP_OVERRIDE_INDEX , value );
252+ ptc_mmio_write (pdev , ptc_instance -> offset , PTC_TEMP_OVERRIDE_ENABLE_INDEX , 1 );
253+ }
254+
255+ return count ;
256+ }
257+
258+ static const struct file_operations ptc_fops = {
259+ .open = simple_open ,
260+ .write = ptc_temperature_write ,
261+ .llseek = generic_file_llseek ,
262+ };
263+
264+ static void ptc_create_debugfs (void )
265+ {
266+ ptc_debugfs = debugfs_create_dir ("platform_temperature_control" , NULL );
267+
268+ debugfs_create_file ("temperature_0" , 0200 , ptc_debugfs , & ptc_instance [0 ], & ptc_fops );
269+ debugfs_create_file ("temperature_1" , 0200 , ptc_debugfs , & ptc_instance [1 ], & ptc_fops );
270+ debugfs_create_file ("temperature_2" , 0200 , ptc_debugfs , & ptc_instance [2 ], & ptc_fops );
271+ }
272+
273+ static void ptc_delete_debugfs (void )
274+ {
275+ debugfs_remove_recursive (ptc_debugfs );
276+ }
212277
213278int proc_thermal_ptc_add (struct pci_dev * pdev , struct proc_thermal_device * proc_priv )
214279{
@@ -217,8 +282,11 @@ int proc_thermal_ptc_add(struct pci_dev *pdev, struct proc_thermal_device *proc_
217282
218283 for (i = 0 ; i < PTC_MAX_INSTANCES ; i ++ ) {
219284 ptc_instance [i ].offset = ptc_offsets [i ];
285+ ptc_instance [i ].pdev = pdev ;
220286 ptc_create_groups (pdev , i , & ptc_instance [i ]);
221287 }
288+
289+ ptc_create_debugfs ();
222290 }
223291
224292 return 0 ;
@@ -234,6 +302,8 @@ void proc_thermal_ptc_remove(struct pci_dev *pdev)
234302
235303 for (i = 0 ; i < PTC_MAX_INSTANCES ; i ++ )
236304 sysfs_remove_group (& pdev -> dev .kobj , & ptc_instance [i ].ptc_attr_group );
305+
306+ ptc_delete_debugfs ();
237307 }
238308}
239309EXPORT_SYMBOL_GPL (proc_thermal_ptc_remove );
0 commit comments