From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933636AbcCKCRp (ORCPT ); Thu, 10 Mar 2016 21:17:45 -0500 Received: from mail-bl2on0085.outbound.protection.outlook.com ([65.55.169.85]:7648 "EHLO na01-bl2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S933443AbcCKCRh convert rfc822-to-8bit (ORCPT ); Thu, 10 Mar 2016 21:17:37 -0500 X-Greylist: delayed 160390 seconds by postgrey-1.27 at vger.kernel.org; Thu, 10 Mar 2016 21:17:36 EST Authentication-Results: spf=none (sender IP is 165.204.84.221) smtp.mailfrom=amd.com; alien8.de; dkim=none (message not signed) header.d=none;alien8.de; dmarc=permerror action=none header.from=amd.com; X-WSS-ID: 0O3URP5-07-HQX-02 X-M-MSG: From: Huang Rui To: Guenter Roeck , Jean Delvare CC: , , , Aravind Gopalakrishnan , Borislav Petkov , Huang Rui Subject: [PATCH v4 4/6] hwmon: (fam15h_power) Introduce a cpu accumulated power reporting algorithm Date: Fri, 11 Mar 2016 10:17:48 +0800 Message-ID: <1457662670-3354-5-git-send-email-ray.huang@amd.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1457662670-3354-1-git-send-email-ray.huang@amd.com> References: <1457662670-3354-1-git-send-email-ray.huang@amd.com> MIME-Version: 1.0 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: 8BIT X-EOPAttributedMessage: 0 X-Forefront-Antispam-Report: CIP:165.204.84.221;CTRY:US;IPV:NLI;EFV:NLI;SFV:NSPM;SFS:(10009020)(6009001)(2980300002)(428002)(199003)(189002)(92566002)(1096002)(586003)(50986999)(105586002)(5820100001)(1220700001)(53416004)(77096005)(87936001)(50226001)(76176999)(81166005)(50466002)(19580405001)(189998001)(2906002)(36756003)(19580395003)(5008740100001)(2950100001)(5001770100001)(229853001)(4326007)(11100500001)(106466001)(33646002)(23676002)(5003600100002)(86362001)(101416001)(47776003);DIR:OUT;SFP:1101;SCL:1;SRVR:BY2PR12MB0711;H:atltwp01.amd.com;FPR:;SPF:None;MLV:sfv;A:1;MX:1;LANG:en; X-MS-Office365-Filtering-Correlation-Id: 23ffed67-44b0-48ca-96bf-08d349534de1 X-Microsoft-Exchange-Diagnostics: 1;BY2PR12MB0711;2:+OC9uTbzQkMmqPqZUgVzrBtxue45Gl09w/iaaKPAy8RO/cdN1e3aOXZzVfgImyPH3uPU/A8/aC2UCJp9EwjTO04i2MFFhKe7kzf0ePTihAIFzALDinqqxs1SrpsLWZA4/zsT5ELbHsDcVpxjWlWkNDrrGTNV63EqSZbC3hSpQwgUSgIvyM7WSQYhtgyt7xq1;3:QpNn22SXJXegZ8Z8+4maIpJkUeK2s7PGi3nB1gkoNdckkFpQKYKLozdj/2JZKNQE7KKfQ4nLIifMRqEW+NdbHm18MsFCx3OJW4RJCEUU2qtb6tr6ZyYzoWXUXgDF6zJZFa6r2CgaB8UkVPGsSmwO+OIYfL0qRUOKws0XR85pAiPS9SHi88jKMGW4VGNx+53ytXJDzHEAMotxADgglBK0lMkxVW2hILXvhKn/05ISWIA=;25:6/C2uoWxExAzkoBEhvfoX6MDJ9rD4Jg7sVEv95CGKV1DMMH83atKLDpEclryZH+TkPDvRZrbWVXb9frJtXZmyngiDSzi1IEjuNqKvQ9is+PmS3fFKrHHCbPox2s/4jTw0nI2zVKWoIMPsT8/I4fRmWW26OJAY65RUf/bo795weGuwBGn4SX+g0Y0jcQETFtZt9vULj2uDUtE17/o9o0LcD5JsDCWpg9GvogB+EuWEh5RuimxJr6rvYWwdv3Vs8Ie3CX5V0ylyU65JpPFxdY8xswkY67G+9w/SYmPWv+uyx9xikCq17R+G0MC9w1DCjnV6TmvYDSzAl2RnGyl41IgDw== X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:BY2PR12MB0711; X-Microsoft-Exchange-Diagnostics: 1;BY2PR12MB0711;20:JKeagbFF1afj0QTWQeexGmVLu7ojFzzF1oSytRuF/kGZP5cElBmoUHyinq92J2odoxzuIvOFssmLWpC7Qb9tYMueRU6+D0EsSl14NNJByLXW7zLTYKI54w/lpnzg9mt6G9V1MmyA8LUJwSRMGM7Zzhrxqo+iMZ/4V1X2cjGefmuJdJuJPFvf84Xg3E9yF9H7//QWKCoDHpAxk5bkOiEI/0R8aARCwtKzQlNh54oLK4Tle7L3SdY2b1GFIkqQSAo6RwMFggyUkq7PQjrOL2SJRQgFAafqUcsH8eB1TRiq40EYDSPFylhJVVvCB4NDnUaxh+825cBK1/objpnDEvB4L830tbieuTAKDjaBKF4pbV3rmLpTnAUqXj4r7e6zUWnBoKRKDVNO1QJcHI+o5pG4mihQc7d5DV7o5PqEPx7iR3tVHb+KnVJZWl8uxbyAh/CbGd58yKNsX9eE7F8GVQ1BW82Uhkm46qrsRDkCc+45K8Z6IDDQ8inYNGS+QZDGOJkU X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(601004)(2401047)(13018025)(13024025)(13015025)(5005006)(8121501046)(13017025)(13023025)(10201501046)(3002001);SRVR:BY2PR12MB0711;BCL:0;PCL:0;RULEID:;SRVR:BY2PR12MB0711; X-Microsoft-Exchange-Diagnostics: 1;BY2PR12MB0711;4:Ikdzio2VnKJGs6D3UdhMhQRut5mlnMKPaQHJTNpvusZzhUPe7HzJhYVHXjc/b9usn6QZPOmVFOUltY98XR8rTqGGCgCUwztX/F5Z99ebBQh+CeL+3NygKvJSArjgbZfVgYnifnqS8ydsZmug6vhT7R0EdBMQeULh79ZVjCjnX3du/l65SklFCtk5BKeC5u7zpE+f/b/uz7iuLCmKadGUkaf/2nyeOPj8klnjGAR5V8WA+dt11GckHuVP13OqxF9in/uhV1cdxvHyMX/9kN6iGUhe7QtFrVt4qj0fFwv5b96EMEPFZ0QCnsJ1RgRiDTyxHWJHSlP9ym/t/VpBwyvIgodcIWIzxKZ5Brg5sMDENcT1he75Ihas/G8NLTTGSB0usUslEki8GAYi0/+EAQRqlaM7FjsTOQzUcfrX2B6GGOfKepOh4uV+o/TbjLn/m94XcxQsJ3/3pv6C3ktPfLzOrw== X-Forefront-PRVS: 087894CD3C X-Microsoft-Exchange-Diagnostics: =?utf-8?B?MTtCWTJQUjEyTUIwNzExOzIzOmhmNXoyaU1rcmljaXZWVmxJcUJCVElCT1pi?= =?utf-8?B?QUQrL0I4YmIrN3R3UGg3K3FyYjU3eG5ta3hROVNNblVza2xQeFR0Y0VoNmVS?= =?utf-8?B?VS9tZ2ZwdXR5SE1PN3EzNXc3SXhPQ24vSDRZSWJuMXVNNXlOVGUyV0FOOUZK?= =?utf-8?B?RTFodndnQ2gvTWg2ZFRINVgvOGNmNm9qSEZ0RFRsNW9USm05VkRjR1hpa1Yz?= =?utf-8?B?N29rVTlMWXhRc2VwQTNkRUJFUnZFczBJb3BDR3Z6cUo2Q2NNdVBoajlzbEJ3?= =?utf-8?B?MFhRanhqR0Z4S3A2U0d4MlRBVmpIeERJZHpyRkpQMG5RV3Bzb05TdTA2M0Jw?= =?utf-8?B?eWtQRFdTYWdUZ1B3aDJ0Z25xaU9tT1UrTnBFMmtuUU5iUCttSGp4NUdBbWRs?= =?utf-8?B?aitINzgrMkJMT0dQSWE1YWRMd1BmRE84MFEyQ21Sa0tKcTFZenZmUFFVUDU1?= =?utf-8?B?eXl4aC9MOTV3bS9pOWkxT29SN1RrN1MrWlpqVS9aRytlSDVNUEM1ZW1GSWxn?= =?utf-8?B?RFNqMGp6dmg0RXJaMS9CMmR0TVZVaTZ4VkpBTnBrVUhDQmFUOGNhMTVORElI?= =?utf-8?B?Z2tBK09XSGpsbVl3SThkZ2Q5TEtaRnNua0NERlAxZkRzV2N3NHR2aWJldG5h?= =?utf-8?B?cVkyVXNjcWVjVHdXemsybGRCRnI1OEtXemxlWjJLNFZvbkp1NmJVSlQ5REVQ?= =?utf-8?B?OVgzZ05BSERBcG81dGlCOU1PWG0zMW42OVJmdmt4NUowNVRwSTlMZFJWdHYr?= =?utf-8?B?c0d1QWtNdkVQUXRIRG0wbTJKVzh4MGU3OW16ZUtEWnEwTHRCeTFUUk13a1Rk?= =?utf-8?B?WEw4UkRvNXIvVmlzL3ZMdzlzOEJNN0U2Y0pnS2cwTlJaUFIzNFA4V0JBQzJO?= =?utf-8?B?SVcyV3JNd016NEU4L1hLSVJIY3liVFgrczBFdHJqNHV0NWdHYUJDVG91YXhp?= =?utf-8?B?MStsM1dSTzZMUENVNGc5M0pJdXA3R3pvY21VS1RDMHdXbElQeStwVGF3a0VX?= =?utf-8?B?OTVnTFZCYTFnbnMxUHlTSFNVbm5TYUpoTVpXbVVSN2xXWUtKYjlaWUdOMFpa?= =?utf-8?B?S1lnMDYwTjZoajN1YjhkQkZqbGMxMDBjSmFScG9XMTlkbEZ0TWNldk5LS0pO?= =?utf-8?B?bVVNcUYxREVDN2VuYkZTV3ZJS0N6N3hqUWRqenhrdzcxSmx1VlpobXZGTW9D?= =?utf-8?B?ci9CUlBzVXQ5T1BFTHZiR0NLZ0FKYm45Q2V0SlVzL2liaENlQjQ5WnZkYUpv?= =?utf-8?B?VWxLcWRIWkxTdm1nazAvajd0Vm05Vi9oR0s4VlFaaHNydTI5WFNNdmpOTlZh?= =?utf-8?Q?hsoNbqa+LR9u/INM43ywOK34CzTXmyL4=3D?= X-Microsoft-Exchange-Diagnostics: 1;BY2PR12MB0711;5:sWXvafgo0pb1MKPkwUfKF7D5WfjGRJtV4SwAAM4BaLCDr3AVvccF0guHPtZpPJyaknQx6gFztXEEJARb5gzN47DXeNmXkzODpYtJ7N//4EDnPQ+vXgxnpt8eyONWah24QF1ZgZt4KYcn5s+KOoAJXw==;24:1XnjIcrqElWsljJJQb9UMOY7IFQG218jZYIyaM/275Ko7dY37mrq5Ur21I9BDUlrLIj2+H40i1hbfktskQjfSZl4A0xjfbKiodn49iz+0fE=;20:f8EW45crabg+WHjJvJzg2bOASh6SwRc0+/+AJRjzy5Eb91MO2HQxPCeQI7wZ+lwXes5h6+/vqBtV0AQCdzRz01J0QIotkDZ9+nX+UuGKm7aE78uKEEaCt7Dg5Y+4Q4RA4mRW9o3asY37biwWOCzRz+d8UpIH8cnMnyteLxGGHRjASM0M0F/1TUmpGY2wYtjvbmcSQ0z3ZWuza2wsLKwu3IoDswSbsFyFSO7Q4neuZHZKqimlCYCCAlq9DksJ98Ct SpamDiagnosticOutput: 1:23 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 11 Mar 2016 02:17:30.3676 (UTC) X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d;Ip=[165.204.84.221];Helo=[atltwp01.amd.com] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: BY2PR12MB0711 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org This patch introduces an algorithm that computes the average power by reading a delta value of “core power accumulator” register during measurement interval, and then dividing delta value by the length of the time interval. User is able to use power1_average entry to measure the processor power consumption and power1_average_interval entry to set the interval. A simple example: ray@hr-ub:~/tip$ sensors fam15h_power-pci-00c4 Adapter: PCI adapter power1: 19.58 mW (avg = 2.55 mW, interval = 0.01 s) (crit = 15.00 W) ... The result is current average processor power consumption in 10 millisecond. The unit of the result is uWatt. Suggested-by: Guenter Roeck Signed-off-by: Huang Rui Cc: Borislav Petkov --- drivers/hwmon/fam15h_power.c | 115 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) diff --git a/drivers/hwmon/fam15h_power.c b/drivers/hwmon/fam15h_power.c index 72aef47..46cbca0 100644 --- a/drivers/hwmon/fam15h_power.c +++ b/drivers/hwmon/fam15h_power.c @@ -27,6 +27,8 @@ #include #include #include +#include +#include #include #include @@ -48,6 +50,9 @@ MODULE_LICENSE("GPL"); #define FAM15H_NUM_GROUPS 2 #define MAX_CUS 8 +/* set maximum interval as 1 second */ +#define MAX_INTERVAL 1000 + #define MSR_F15H_CU_PWR_ACCUMULATOR 0xc001007a #define MSR_F15H_CU_MAX_PWR_ACCUMULATOR 0xc001007b #define MSR_F15H_PTSC 0xc0010280 @@ -68,6 +73,9 @@ struct fam15h_power_data { u64 cu_acc_power[MAX_CUS]; /* performance timestamp counter */ u64 cpu_sw_pwr_ptsc[MAX_CUS]; + /* online/offline status of current compute unit */ + int cu_on[MAX_CUS]; + unsigned long power_period; }; static ssize_t show_power(struct device *dev, @@ -145,6 +153,8 @@ static void do_read_registers_on_cu(void *_data) rdmsrl_safe(MSR_F15H_CU_PWR_ACCUMULATOR, &data->cu_acc_power[cu]); rdmsrl_safe(MSR_F15H_PTSC, &data->cpu_sw_pwr_ptsc[cu]); + + data->cu_on[cu] = 1; } /* @@ -161,6 +171,8 @@ static int read_registers(struct fam15h_power_data *data) if (!ret) return -ENOMEM; + memset(data->cu_on, 0, sizeof(int) * MAX_CUS); + get_online_cpus(); this_cpu = get_cpu(); @@ -188,18 +200,113 @@ static int read_registers(struct fam15h_power_data *data) return 0; } +static ssize_t acc_show_power(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct fam15h_power_data *data = dev_get_drvdata(dev); + u64 prev_cu_acc_power[MAX_CUS], prev_ptsc[MAX_CUS], + jdelta[MAX_CUS]; + u64 tdelta, avg_acc; + int cu, cu_num, ret; + signed long leftover; + + cu_num = boot_cpu_data.x86_max_cores / smp_num_siblings; + + ret = read_registers(data); + if (ret) + return 0; + + for (cu = 0; cu < cu_num; cu++) { + prev_cu_acc_power[cu] = data->cu_acc_power[cu]; + prev_ptsc[cu] = data->cpu_sw_pwr_ptsc[cu]; + } + + leftover = schedule_timeout_interruptible(msecs_to_jiffies(data->power_period)); + if (leftover) + return 0; + + ret = read_registers(data); + if (ret) + return 0; + + for (cu = 0, avg_acc = 0; cu < cu_num; cu++) { + /* check if current compute unit is online */ + if (data->cu_on[cu] == 0) + continue; + + if (data->cu_acc_power[cu] < prev_cu_acc_power[cu]) { + jdelta[cu] = data->max_cu_acc_power + data->cu_acc_power[cu]; + jdelta[cu] -= prev_cu_acc_power[cu]; + } else { + jdelta[cu] = data->cu_acc_power[cu] - prev_cu_acc_power[cu]; + } + tdelta = data->cpu_sw_pwr_ptsc[cu] - prev_ptsc[cu]; + jdelta[cu] *= data->cpu_pwr_sample_ratio * 1000; + do_div(jdelta[cu], tdelta); + + /* the unit is microWatt */ + avg_acc += jdelta[cu]; + } + + return sprintf(buf, "%llu\n", (unsigned long long)avg_acc); +} +static DEVICE_ATTR(power1_average, S_IRUGO, acc_show_power, NULL); + +static ssize_t acc_show_power_period(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct fam15h_power_data *data = dev_get_drvdata(dev); + + return sprintf(buf, "%lu\n", data->power_period); +} + +static ssize_t acc_set_power_period(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct fam15h_power_data *data = dev_get_drvdata(dev); + unsigned long temp; + int ret; + + ret = kstrtoul(buf, 10, &temp); + if (ret) + return ret; + + if (temp > MAX_INTERVAL) + return -EINVAL; + + /* the interval value should be greater than 0 */ + if (temp <= 0) + return -EINVAL; + + data->power_period = temp; + + return count; +} +static DEVICE_ATTR(power1_average_interval, S_IRUGO | S_IWUSR, + acc_show_power_period, acc_set_power_period); + static int fam15h_power_init_attrs(struct pci_dev *pdev, struct fam15h_power_data *data) { int n = FAM15H_MIN_NUM_ATTRS; struct attribute **fam15h_power_attrs; struct cpuinfo_x86 *c = &boot_cpu_data; + u32 cpuid; if (c->x86 == 0x15 && (c->x86_model <= 0xf || (c->x86_model >= 0x60 && c->x86_model <= 0x7f))) n += 1; + cpuid = cpuid_edx(0x80000007); + + /* check if processor supports accumulated power */ + if (cpuid & BIT(12)) + n += 2; + fam15h_power_attrs = devm_kcalloc(&pdev->dev, n, sizeof(*fam15h_power_attrs), GFP_KERNEL); @@ -214,6 +321,11 @@ static int fam15h_power_init_attrs(struct pci_dev *pdev, (c->x86_model >= 0x60 && c->x86_model <= 0x7f))) fam15h_power_attrs[n++] = &dev_attr_power1_input.attr; + if (cpuid & BIT(12)) { + fam15h_power_attrs[n++] = &dev_attr_power1_average.attr; + fam15h_power_attrs[n++] = &dev_attr_power1_average_interval.attr; + } + data->group.attrs = fam15h_power_attrs; return 0; @@ -326,6 +438,9 @@ static int fam15h_power_init_data(struct pci_dev *f4, data->max_cu_acc_power = tmp; + /* set default interval as 10 ms */ + data->power_period = 10; + return read_registers(data); } -- 1.9.1