Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[pull] master from amd:master #10

Closed
wants to merge 10 commits into from
10 changes: 7 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ Supported chips:

* AMD Family 19h Processors: Model 01h and 10h

* AMD Family 19h Processors: Model 00h, 11h, A0h, 90h

* AMD Family 1Ah Processors: Model 00h, 02h, 11h, 10h

Prefix: 'amd_energy'

Addresses used: RAPL MSRs
Expand Down Expand Up @@ -66,7 +70,7 @@ reading those registers from the sibling threads would result
in duplicate values. Hence, energy counter entries are not
populated for the siblings.

Energy Caluclation
Energy Calculation
------------------

Energy information (in Joules) is based on the multiplier,
Expand Down Expand Up @@ -94,7 +98,7 @@ The Core energy register may wrap around after several days.
To improve the wrap around time, a kernel thread is implemented
to accumulate the socket energy counters and one core energy counter
per run to a respective 64-bit counter. The kernel thread starts
running during probe, wakes up every 100secs and stops running
running during probe, wakes up every 100 secs and stops running
when driver is removed.

Frequency of the accumulator thread is set during the probe
Expand Down Expand Up @@ -199,7 +203,7 @@ Install the module using DKMS:
#> sudo dkms install --force amd_energy/1.0 -k linux_version
Module is built: /lib/modules/linux_version/updates/dkms/

Notes: It is required to have specific linux verion header in /usr/src
Notes: It is required to have specific linux version header in /usr/src

To remove module from dkms tree
#> sudo dkms remove -m amd_energy/1.0 --all
Expand Down
40 changes: 31 additions & 9 deletions amd_energy.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
#include <linux/topology.h>
#include <linux/types.h>

#include <generated/uapi/linux/version.h>

#define DRV_MODULE_DESCRIPTION "AMD energy driver"
#define DRV_MODULE_VERSION "1.0"

Expand Down Expand Up @@ -108,7 +110,8 @@ static void read_accumulate(struct amd_energy_data *data)

for (sock = 0; sock < data->nr_socks; sock++) {
scpu = cpumask_first_and(cpu_online_mask,
cpumask_of_node(sock));
topology_die_cpumask
((data->nr_cpus/data->nr_socks) * sock ));

accumulate_delta(data, data->nr_cpus + sock,
scpu, ENERGY_PKG_MSR);
Expand All @@ -132,9 +135,9 @@ static void amd_add_delta(struct amd_energy_data *data, int ch,

mutex_lock(&data->lock);
rdmsrl_safe_on_cpu(cpu, reg, &input);
input &= AMD_ENERGY_MASK;

if (!data->do_not_accum) {
input &= AMD_ENERGY_MASK;
accum = &data->accums[ch];
if (input >= accum->prev_value)
input += accum->energy_ctr -
Expand All @@ -160,8 +163,9 @@ static int amd_energy_read(struct device *dev,

if (channel >= data->nr_cpus) {
cpu = cpumask_first_and(cpu_online_mask,
cpumask_of_node
(channel - data->nr_cpus));
topology_die_cpumask
((data->nr_cpus/data->nr_socks) *
(channel - data->nr_cpus)));
reg = ENERGY_PKG_MSR;
} else {
cpu = channel;
Expand Down Expand Up @@ -214,7 +218,6 @@ static int amd_create_sensor(struct device *dev,
enum hwmon_sensor_types type, u32 config)
{
struct hwmon_channel_info *info = &data->energy_info;
struct cpuinfo_x86 *c = &boot_cpu_data;
struct sensor_accumulator *accums;
int i, num_siblings, cpus, sockets;
u32 *s_config;
Expand All @@ -233,7 +236,12 @@ static int amd_create_sensor(struct device *dev,
* c->x86_max_cores is the linux count of physical cores
* total physical cores/ core per socket gives total number of sockets.
*/
#if LINUX_VERSION_CODE <= KERNEL_VERSION(6, 8, 0)
struct cpuinfo_x86 *c = &boot_cpu_data;
sockets = cpus / c->x86_max_cores;
#else
sockets = cpus / topology_num_cores_per_package();
#endif

s_config = devm_kcalloc(dev, cpus + sockets + 1,
sizeof(u32), GFP_KERNEL);
Expand Down Expand Up @@ -323,8 +331,13 @@ static int amd_energy_probe(struct platform_device *pdev)
* of the energy counters are not necessary.
*/
if (!x86_match_cpu(bit32_rapl_cpus)) {
data->do_not_accum = true;
return 0;
if (boot_cpu_data.x86 == 0x19 &&
boot_cpu_data.x86_model == 0x0) {
data->do_not_accum = false;
} else {
data->do_not_accum = true;
return 0;
}
}

data->wrap_accumulate = kthread_run(energy_accumulator, data,
Expand Down Expand Up @@ -364,6 +377,12 @@ static const struct x86_cpu_id cpu_ids[] __initconst = {
X86_MATCH_VENDOR_FAM_MODEL(AMD, 0x19, 0x01, NULL),
X86_MATCH_VENDOR_FAM_MODEL(AMD, 0x19, 0x10, NULL),
X86_MATCH_VENDOR_FAM_MODEL(AMD, 0x19, 0x30, NULL),
X86_MATCH_VENDOR_FAM_MODEL(AMD, 0x19, 0x11, NULL),
X86_MATCH_VENDOR_FAM_MODEL(AMD, 0x19, 0xA0, NULL),
X86_MATCH_VENDOR_FAM_MODEL(AMD, 0x19, 0x90, NULL),
X86_MATCH_VENDOR_FAM_MODEL(AMD, 0x1A, 0x10, NULL),
X86_MATCH_VENDOR_FAM_MODEL(AMD, 0x1A, 0x02, NULL),
X86_MATCH_VENDOR_FAM_MODEL(AMD, 0x1A, 0x11, NULL),
{}
};
MODULE_DEVICE_TABLE(x86cpu, cpu_ids);
Expand All @@ -372,8 +391,11 @@ static int __init amd_energy_init(void)
{
int ret;

if (!x86_match_cpu(cpu_ids))
return -ENODEV;
if (!x86_match_cpu(cpu_ids)) {
if (!((boot_cpu_data.x86 == 0x1A || boot_cpu_data.x86 == 0x19) &&
(boot_cpu_data.x86_model == 0x0)))
return -ENODEV;
}

ret = platform_driver_register(&amd_energy_driver);
if (ret)
Expand Down