summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorHuang Rui <ray.huang@amd.com>2015-10-30 05:56:55 -0400
committerGuenter Roeck <linux@roeck-us.net>2015-10-31 18:37:17 -0400
commit7deb14b1316def5d4c85f99718d9e530d53cef4e (patch)
tree7662d0677b0a6703eb2d8a19a2437dffb044cda4 /drivers
parent5aa4e83dd54a3b33d0f2fbab0a1f06a3614a5949 (diff)
hwmon: (fam15h_power) Refactor attributes for dynamically added
Attributes depend on the CPU model the driver gets loaded on. Therefore, add those attributes dynamically at init time. This is more flexible to control the different attributes on different platforms. Suggested-by: Borislav Petkov <bp@alien8.de> Signed-off-by: Huang Rui <ray.huang@amd.com> Cc: Guenter Roeck <linux@roeck-us.net> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Ingo Molnar <mingo@kernel.org> Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/hwmon/fam15h_power.c70
1 files changed, 45 insertions, 25 deletions
diff --git a/drivers/hwmon/fam15h_power.c b/drivers/hwmon/fam15h_power.c
index e80ee23b62d3..2d899fd75f2a 100644
--- a/drivers/hwmon/fam15h_power.c
+++ b/drivers/hwmon/fam15h_power.c
@@ -41,12 +41,17 @@ MODULE_LICENSE("GPL");
41#define REG_TDP_RUNNING_AVERAGE 0xe0 41#define REG_TDP_RUNNING_AVERAGE 0xe0
42#define REG_TDP_LIMIT3 0xe8 42#define REG_TDP_LIMIT3 0xe8
43 43
44#define FAM15H_MIN_NUM_ATTRS 2
45#define FAM15H_NUM_GROUPS 2
46
44struct fam15h_power_data { 47struct fam15h_power_data {
45 struct pci_dev *pdev; 48 struct pci_dev *pdev;
46 unsigned int tdp_to_watts; 49 unsigned int tdp_to_watts;
47 unsigned int base_tdp; 50 unsigned int base_tdp;
48 unsigned int processor_pwr_watts; 51 unsigned int processor_pwr_watts;
49 unsigned int cpu_pwr_sample_ratio; 52 unsigned int cpu_pwr_sample_ratio;
53 const struct attribute_group *groups[FAM15H_NUM_GROUPS];
54 struct attribute_group group;
50}; 55};
51 56
52static ssize_t show_power(struct device *dev, 57static ssize_t show_power(struct device *dev,
@@ -105,29 +110,31 @@ static ssize_t show_power_crit(struct device *dev,
105} 110}
106static DEVICE_ATTR(power1_crit, S_IRUGO, show_power_crit, NULL); 111static DEVICE_ATTR(power1_crit, S_IRUGO, show_power_crit, NULL);
107 112
108static umode_t fam15h_power_is_visible(struct kobject *kobj, 113static int fam15h_power_init_attrs(struct pci_dev *pdev,
109 struct attribute *attr, 114 struct fam15h_power_data *data)
110 int index)
111{ 115{
112 /* power1_input is only reported for Fam15h, Models 00h-0fh */ 116 int n = FAM15H_MIN_NUM_ATTRS;
113 if (attr == &dev_attr_power1_input.attr && 117 struct attribute **fam15h_power_attrs;
114 (boot_cpu_data.x86 != 0x15 || boot_cpu_data.x86_model > 0xf))
115 return 0;
116 118
117 return attr->mode; 119 if (boot_cpu_data.x86 == 0x15 && boot_cpu_data.x86_model <= 0xf)
118} 120 n += 1;
119 121
120static struct attribute *fam15h_power_attrs[] = { 122 fam15h_power_attrs = devm_kcalloc(&pdev->dev, n,
121 &dev_attr_power1_input.attr, 123 sizeof(*fam15h_power_attrs),
122 &dev_attr_power1_crit.attr, 124 GFP_KERNEL);
123 NULL
124};
125 125
126static const struct attribute_group fam15h_power_group = { 126 if (!fam15h_power_attrs)
127 .attrs = fam15h_power_attrs, 127 return -ENOMEM;
128 .is_visible = fam15h_power_is_visible, 128
129}; 129 n = 0;
130__ATTRIBUTE_GROUPS(fam15h_power); 130 fam15h_power_attrs[n++] = &dev_attr_power1_crit.attr;
131 if (boot_cpu_data.x86 == 0x15 && boot_cpu_data.x86_model <= 0xf)
132 fam15h_power_attrs[n++] = &dev_attr_power1_input.attr;
133
134 data->group.attrs = fam15h_power_attrs;
135
136 return 0;
137}
131 138
132static bool should_load_on_this_node(struct pci_dev *f4) 139static bool should_load_on_this_node(struct pci_dev *f4)
133{ 140{
@@ -186,11 +193,12 @@ static int fam15h_power_resume(struct pci_dev *pdev)
186#define fam15h_power_resume NULL 193#define fam15h_power_resume NULL
187#endif 194#endif
188 195
189static void fam15h_power_init_data(struct pci_dev *f4, 196static int fam15h_power_init_data(struct pci_dev *f4,
190 struct fam15h_power_data *data) 197 struct fam15h_power_data *data)
191{ 198{
192 u32 val, eax, ebx, ecx, edx; 199 u32 val, eax, ebx, ecx, edx;
193 u64 tmp; 200 u64 tmp;
201 int ret;
194 202
195 pci_read_config_dword(f4, REG_PROCESSOR_TDP, &val); 203 pci_read_config_dword(f4, REG_PROCESSOR_TDP, &val);
196 data->base_tdp = val >> 16; 204 data->base_tdp = val >> 16;
@@ -211,11 +219,15 @@ static void fam15h_power_init_data(struct pci_dev *f4,
211 /* convert to microWatt */ 219 /* convert to microWatt */
212 data->processor_pwr_watts = (tmp * 15625) >> 10; 220 data->processor_pwr_watts = (tmp * 15625) >> 10;
213 221
222 ret = fam15h_power_init_attrs(f4, data);
223 if (ret)
224 return ret;
225
214 cpuid(0x80000007, &eax, &ebx, &ecx, &edx); 226 cpuid(0x80000007, &eax, &ebx, &ecx, &edx);
215 227
216 /* CPUID Fn8000_0007:EDX[12] indicates to support accumulated power */ 228 /* CPUID Fn8000_0007:EDX[12] indicates to support accumulated power */
217 if (!(edx & BIT(12))) 229 if (!(edx & BIT(12)))
218 return; 230 return 0;
219 231
220 /* 232 /*
221 * determine the ratio of the compute unit power accumulator 233 * determine the ratio of the compute unit power accumulator
@@ -223,14 +235,17 @@ static void fam15h_power_init_data(struct pci_dev *f4,
223 * Fn8000_0007:ECX 235 * Fn8000_0007:ECX
224 */ 236 */
225 data->cpu_pwr_sample_ratio = ecx; 237 data->cpu_pwr_sample_ratio = ecx;
238
239 return 0;
226} 240}
227 241
228static int fam15h_power_probe(struct pci_dev *pdev, 242static int fam15h_power_probe(struct pci_dev *pdev,
229 const struct pci_device_id *id) 243 const struct pci_device_id *id)
230{ 244{
231 struct fam15h_power_data *data; 245 struct fam15h_power_data *data;
232 struct device *dev = &pdev->dev; 246 struct device *dev = &pdev->dev;
233 struct device *hwmon_dev; 247 struct device *hwmon_dev;
248 int ret;
234 249
235 /* 250 /*
236 * though we ignore every other northbridge, we still have to 251 * though we ignore every other northbridge, we still have to
@@ -246,12 +261,17 @@ static int fam15h_power_probe(struct pci_dev *pdev,
246 if (!data) 261 if (!data)
247 return -ENOMEM; 262 return -ENOMEM;
248 263
249 fam15h_power_init_data(pdev, data); 264 ret = fam15h_power_init_data(pdev, data);
265 if (ret)
266 return ret;
267
250 data->pdev = pdev; 268 data->pdev = pdev;
251 269
270 data->groups[0] = &data->group;
271
252 hwmon_dev = devm_hwmon_device_register_with_groups(dev, "fam15h_power", 272 hwmon_dev = devm_hwmon_device_register_with_groups(dev, "fam15h_power",
253 data, 273 data,
254 fam15h_power_groups); 274 &data->groups[0]);
255 return PTR_ERR_OR_ZERO(hwmon_dev); 275 return PTR_ERR_OR_ZERO(hwmon_dev);
256} 276}
257 277