1108 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * A hwmon driver for the IBM System Director Active Energy Manager (AEM)4 * temperature/power/energy sensors and capping functionality.5 * Copyright (C) 2008 IBM6 *7 * Author: Darrick J. Wong <darrick.wong@oracle.com>8 */9 10#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt11 12#include <linux/ipmi.h>13#include <linux/module.h>14#include <linux/hwmon.h>15#include <linux/hwmon-sysfs.h>16#include <linux/jiffies.h>17#include <linux/mutex.h>18#include <linux/kdev_t.h>19#include <linux/spinlock.h>20#include <linux/idr.h>21#include <linux/slab.h>22#include <linux/sched.h>23#include <linux/platform_device.h>24#include <linux/math64.h>25#include <linux/time.h>26#include <linux/err.h>27 28#define REFRESH_INTERVAL (HZ)29#define IPMI_TIMEOUT (30 * HZ)30#define DRVNAME "aem"31 32#define AEM_NETFN 0x2E33 34#define AEM_FIND_FW_CMD 0x8035#define AEM_ELEMENT_CMD 0x8136#define AEM_FW_INSTANCE_CMD 0x8237 38#define AEM_READ_ELEMENT_CFG 0x8039#define AEM_READ_BUFFER 0x8140#define AEM_READ_REGISTER 0x8241#define AEM_WRITE_REGISTER 0x8342#define AEM_SET_REG_MASK 0x8443#define AEM_CLEAR_REG_MASK 0x8544#define AEM_READ_ELEMENT_CFG2 0x8645 46#define AEM_CONTROL_ELEMENT 047#define AEM_ENERGY_ELEMENT 148#define AEM_CLOCK_ELEMENT 449#define AEM_POWER_CAP_ELEMENT 750#define AEM_EXHAUST_ELEMENT 951#define AEM_POWER_ELEMENT 1052 53#define AEM_MODULE_TYPE_ID 0x000154 55#define AEM2_NUM_ENERGY_REGS 256#define AEM2_NUM_PCAP_REGS 657#define AEM2_NUM_TEMP_REGS 258#define AEM2_NUM_SENSORS 1459 60#define AEM1_NUM_ENERGY_REGS 161#define AEM1_NUM_SENSORS 362 63/* AEM 2.x has more energy registers */64#define AEM_NUM_ENERGY_REGS AEM2_NUM_ENERGY_REGS65/* AEM 2.x needs more sensor files */66#define AEM_NUM_SENSORS AEM2_NUM_SENSORS67 68#define POWER_CAP 069#define POWER_CAP_MAX_HOTPLUG 170#define POWER_CAP_MAX 271#define POWER_CAP_MIN_WARNING 372#define POWER_CAP_MIN 473#define POWER_AUX 574 75#define AEM_DEFAULT_POWER_INTERVAL 100076#define AEM_MIN_POWER_INTERVAL 20077#define UJ_PER_MJ 1000L78 79static DEFINE_IDA(aem_ida);80 81static struct platform_driver aem_driver = {82 .driver = {83 .name = DRVNAME,84 .bus = &platform_bus_type,85 }86};87 88struct aem_ipmi_data {89 struct completion read_complete;90 struct ipmi_addr address;91 struct ipmi_user *user;92 int interface;93 94 struct kernel_ipmi_msg tx_message;95 long tx_msgid;96 97 void *rx_msg_data;98 unsigned short rx_msg_len;99 unsigned char rx_result;100 int rx_recv_type;101 102 struct device *bmc_device;103};104 105struct aem_ro_sensor_template {106 char *label;107 ssize_t (*show)(struct device *dev,108 struct device_attribute *devattr,109 char *buf);110 int index;111};112 113struct aem_rw_sensor_template {114 char *label;115 ssize_t (*show)(struct device *dev,116 struct device_attribute *devattr,117 char *buf);118 ssize_t (*set)(struct device *dev,119 struct device_attribute *devattr,120 const char *buf, size_t count);121 int index;122};123 124struct aem_data {125 struct list_head list;126 127 struct device *hwmon_dev;128 struct platform_device *pdev;129 struct mutex lock;130 bool valid;131 unsigned long last_updated; /* In jiffies */132 u8 ver_major;133 u8 ver_minor;134 u8 module_handle;135 int id;136 struct aem_ipmi_data ipmi;137 138 /* Function and buffer to update sensors */139 void (*update)(struct aem_data *data);140 struct aem_read_sensor_resp *rs_resp;141 142 /*143 * AEM 1.x sensors:144 * Available sensors:145 * Energy meter146 * Power meter147 *148 * AEM 2.x sensors:149 * Two energy meters150 * Two power meters151 * Two temperature sensors152 * Six power cap registers153 */154 155 /* sysfs attrs */156 struct sensor_device_attribute sensors[AEM_NUM_SENSORS];157 158 /* energy use in mJ */159 u64 energy[AEM_NUM_ENERGY_REGS];160 161 /* power sampling interval in ms */162 unsigned long power_period[AEM_NUM_ENERGY_REGS];163 164 /* Everything past here is for AEM2 only */165 166 /* power caps in dW */167 u16 pcap[AEM2_NUM_PCAP_REGS];168 169 /* exhaust temperature in C */170 u8 temp[AEM2_NUM_TEMP_REGS];171};172 173/* Data structures returned by the AEM firmware */174struct aem_iana_id {175 u8 bytes[3];176};177static struct aem_iana_id system_x_id = {178 .bytes = {0x4D, 0x4F, 0x00}179};180 181/* These are used to find AEM1 instances */182struct aem_find_firmware_req {183 struct aem_iana_id id;184 u8 rsvd;185 __be16 index;186 __be16 module_type_id;187} __packed;188 189struct aem_find_firmware_resp {190 struct aem_iana_id id;191 u8 num_instances;192} __packed;193 194/* These are used to find AEM2 instances */195struct aem_find_instance_req {196 struct aem_iana_id id;197 u8 instance_number;198 __be16 module_type_id;199} __packed;200 201struct aem_find_instance_resp {202 struct aem_iana_id id;203 u8 num_instances;204 u8 major;205 u8 minor;206 u8 module_handle;207 u16 record_id;208} __packed;209 210/* These are used to query sensors */211struct aem_read_sensor_req {212 struct aem_iana_id id;213 u8 module_handle;214 u8 element;215 u8 subcommand;216 u8 reg;217 u8 rx_buf_size;218} __packed;219 220struct aem_read_sensor_resp {221 struct aem_iana_id id;222 u8 bytes[];223} __packed;224 225/* Data structures to talk to the IPMI layer */226struct aem_driver_data {227 struct list_head aem_devices;228 struct ipmi_smi_watcher bmc_events;229 struct ipmi_user_hndl ipmi_hndlrs;230};231 232static void aem_register_bmc(int iface, struct device *dev);233static void aem_bmc_gone(int iface);234static void aem_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data);235 236static void aem_remove_sensors(struct aem_data *data);237static int aem1_find_sensors(struct aem_data *data);238static int aem2_find_sensors(struct aem_data *data);239static void update_aem1_sensors(struct aem_data *data);240static void update_aem2_sensors(struct aem_data *data);241 242static struct aem_driver_data driver_data = {243 .aem_devices = LIST_HEAD_INIT(driver_data.aem_devices),244 .bmc_events = {245 .owner = THIS_MODULE,246 .new_smi = aem_register_bmc,247 .smi_gone = aem_bmc_gone,248 },249 .ipmi_hndlrs = {250 .ipmi_recv_hndl = aem_msg_handler,251 },252};253 254/* Functions to talk to the IPMI layer */255 256/* Initialize IPMI address, message buffers and user data */257static int aem_init_ipmi_data(struct aem_ipmi_data *data, int iface,258 struct device *bmc)259{260 int err;261 262 init_completion(&data->read_complete);263 data->bmc_device = bmc;264 265 /* Initialize IPMI address */266 data->address.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;267 data->address.channel = IPMI_BMC_CHANNEL;268 data->address.data[0] = 0;269 data->interface = iface;270 271 /* Initialize message buffers */272 data->tx_msgid = 0;273 data->tx_message.netfn = AEM_NETFN;274 275 /* Create IPMI messaging interface user */276 err = ipmi_create_user(data->interface, &driver_data.ipmi_hndlrs,277 data, &data->user);278 if (err < 0) {279 dev_err(bmc,280 "Unable to register user with IPMI interface %d\n",281 data->interface);282 return err;283 }284 285 return 0;286}287 288/* Send an IPMI command */289static int aem_send_message(struct aem_ipmi_data *data)290{291 int err;292 293 err = ipmi_validate_addr(&data->address, sizeof(data->address));294 if (err)295 goto out;296 297 data->tx_msgid++;298 err = ipmi_request_settime(data->user, &data->address, data->tx_msgid,299 &data->tx_message, data, 0, 0, 0);300 if (err)301 goto out1;302 303 return 0;304out1:305 dev_err(data->bmc_device, "request_settime=%x\n", err);306 return err;307out:308 dev_err(data->bmc_device, "validate_addr=%x\n", err);309 return err;310}311 312/* Dispatch IPMI messages to callers */313static void aem_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data)314{315 unsigned short rx_len;316 struct aem_ipmi_data *data = user_msg_data;317 318 if (msg->msgid != data->tx_msgid) {319 dev_err(data->bmc_device,320 "Mismatch between received msgid (%02x) and transmitted msgid (%02x)!\n",321 (int)msg->msgid,322 (int)data->tx_msgid);323 ipmi_free_recv_msg(msg);324 return;325 }326 327 data->rx_recv_type = msg->recv_type;328 if (msg->msg.data_len > 0)329 data->rx_result = msg->msg.data[0];330 else331 data->rx_result = IPMI_UNKNOWN_ERR_COMPLETION_CODE;332 333 if (msg->msg.data_len > 1) {334 rx_len = msg->msg.data_len - 1;335 if (data->rx_msg_len < rx_len)336 rx_len = data->rx_msg_len;337 data->rx_msg_len = rx_len;338 memcpy(data->rx_msg_data, msg->msg.data + 1, data->rx_msg_len);339 } else340 data->rx_msg_len = 0;341 342 ipmi_free_recv_msg(msg);343 complete(&data->read_complete);344}345 346/* Sensor support functions */347 348/* Read a sensor value; must be called with data->lock held */349static int aem_read_sensor(struct aem_data *data, u8 elt, u8 reg,350 void *buf, size_t size)351{352 int rs_size, res;353 struct aem_read_sensor_req rs_req;354 /* Use preallocated rx buffer */355 struct aem_read_sensor_resp *rs_resp = data->rs_resp;356 struct aem_ipmi_data *ipmi = &data->ipmi;357 358 /* AEM registers are 1, 2, 4 or 8 bytes */359 switch (size) {360 case 1:361 case 2:362 case 4:363 case 8:364 break;365 default:366 return -EINVAL;367 }368 369 rs_req.id = system_x_id;370 rs_req.module_handle = data->module_handle;371 rs_req.element = elt;372 rs_req.subcommand = AEM_READ_REGISTER;373 rs_req.reg = reg;374 rs_req.rx_buf_size = size;375 376 ipmi->tx_message.cmd = AEM_ELEMENT_CMD;377 ipmi->tx_message.data = (char *)&rs_req;378 ipmi->tx_message.data_len = sizeof(rs_req);379 380 rs_size = sizeof(*rs_resp) + size;381 ipmi->rx_msg_data = rs_resp;382 ipmi->rx_msg_len = rs_size;383 384 aem_send_message(ipmi);385 386 res = wait_for_completion_timeout(&ipmi->read_complete, IPMI_TIMEOUT);387 if (!res) {388 res = -ETIMEDOUT;389 goto out;390 }391 392 if (ipmi->rx_result || ipmi->rx_msg_len != rs_size ||393 memcmp(&rs_resp->id, &system_x_id, sizeof(system_x_id))) {394 res = -ENOENT;395 goto out;396 }397 398 switch (size) {399 case 1: {400 u8 *x = buf;401 *x = rs_resp->bytes[0];402 break;403 }404 case 2: {405 u16 *x = buf;406 *x = be16_to_cpup((__be16 *)rs_resp->bytes);407 break;408 }409 case 4: {410 u32 *x = buf;411 *x = be32_to_cpup((__be32 *)rs_resp->bytes);412 break;413 }414 case 8: {415 u64 *x = buf;416 *x = be64_to_cpup((__be64 *)rs_resp->bytes);417 break;418 }419 }420 res = 0;421 422out:423 return res;424}425 426/* Update AEM energy registers */427static void update_aem_energy_one(struct aem_data *data, int which)428{429 aem_read_sensor(data, AEM_ENERGY_ELEMENT, which,430 &data->energy[which], 8);431}432 433static void update_aem_energy(struct aem_data *data)434{435 update_aem_energy_one(data, 0);436 if (data->ver_major < 2)437 return;438 update_aem_energy_one(data, 1);439}440 441/* Update all AEM1 sensors */442static void update_aem1_sensors(struct aem_data *data)443{444 mutex_lock(&data->lock);445 if (time_before(jiffies, data->last_updated + REFRESH_INTERVAL) &&446 data->valid)447 goto out;448 449 update_aem_energy(data);450out:451 mutex_unlock(&data->lock);452}453 454/* Update all AEM2 sensors */455static void update_aem2_sensors(struct aem_data *data)456{457 int i;458 459 mutex_lock(&data->lock);460 if (time_before(jiffies, data->last_updated + REFRESH_INTERVAL) &&461 data->valid)462 goto out;463 464 update_aem_energy(data);465 aem_read_sensor(data, AEM_EXHAUST_ELEMENT, 0, &data->temp[0], 1);466 aem_read_sensor(data, AEM_EXHAUST_ELEMENT, 1, &data->temp[1], 1);467 468 for (i = POWER_CAP; i <= POWER_AUX; i++)469 aem_read_sensor(data, AEM_POWER_CAP_ELEMENT, i,470 &data->pcap[i], 2);471out:472 mutex_unlock(&data->lock);473}474 475/* Delete an AEM instance */476static void aem_delete(struct aem_data *data)477{478 list_del(&data->list);479 aem_remove_sensors(data);480 kfree(data->rs_resp);481 hwmon_device_unregister(data->hwmon_dev);482 ipmi_destroy_user(data->ipmi.user);483 platform_set_drvdata(data->pdev, NULL);484 platform_device_unregister(data->pdev);485 ida_free(&aem_ida, data->id);486 kfree(data);487}488 489/* Probe functions for AEM1 devices */490 491/* Retrieve version and module handle for an AEM1 instance */492static int aem_find_aem1_count(struct aem_ipmi_data *data)493{494 int res;495 struct aem_find_firmware_req ff_req;496 struct aem_find_firmware_resp ff_resp;497 498 ff_req.id = system_x_id;499 ff_req.index = 0;500 ff_req.module_type_id = cpu_to_be16(AEM_MODULE_TYPE_ID);501 502 data->tx_message.cmd = AEM_FIND_FW_CMD;503 data->tx_message.data = (char *)&ff_req;504 data->tx_message.data_len = sizeof(ff_req);505 506 data->rx_msg_data = &ff_resp;507 data->rx_msg_len = sizeof(ff_resp);508 509 aem_send_message(data);510 511 res = wait_for_completion_timeout(&data->read_complete, IPMI_TIMEOUT);512 if (!res)513 return -ETIMEDOUT;514 515 if (data->rx_result || data->rx_msg_len != sizeof(ff_resp) ||516 memcmp(&ff_resp.id, &system_x_id, sizeof(system_x_id)))517 return -ENOENT;518 519 return ff_resp.num_instances;520}521 522/* Find and initialize one AEM1 instance */523static int aem_init_aem1_inst(struct aem_ipmi_data *probe, u8 module_handle)524{525 struct aem_data *data;526 int i;527 int res = -ENOMEM;528 529 data = kzalloc(sizeof(*data), GFP_KERNEL);530 if (!data)531 return res;532 mutex_init(&data->lock);533 534 /* Copy instance data */535 data->ver_major = 1;536 data->ver_minor = 0;537 data->module_handle = module_handle;538 for (i = 0; i < AEM1_NUM_ENERGY_REGS; i++)539 data->power_period[i] = AEM_DEFAULT_POWER_INTERVAL;540 541 /* Create sub-device for this fw instance */542 data->id = ida_alloc(&aem_ida, GFP_KERNEL);543 if (data->id < 0)544 goto id_err;545 546 data->pdev = platform_device_alloc(DRVNAME, data->id);547 if (!data->pdev)548 goto dev_err;549 data->pdev->dev.driver = &aem_driver.driver;550 551 res = platform_device_add(data->pdev);552 if (res)553 goto dev_add_err;554 555 platform_set_drvdata(data->pdev, data);556 557 /* Set up IPMI interface */558 res = aem_init_ipmi_data(&data->ipmi, probe->interface,559 probe->bmc_device);560 if (res)561 goto ipmi_err;562 563 /* Register with hwmon */564 data->hwmon_dev = hwmon_device_register(&data->pdev->dev);565 if (IS_ERR(data->hwmon_dev)) {566 dev_err(&data->pdev->dev,567 "Unable to register hwmon device for IPMI interface %d\n",568 probe->interface);569 res = PTR_ERR(data->hwmon_dev);570 goto hwmon_reg_err;571 }572 573 data->update = update_aem1_sensors;574 data->rs_resp = kzalloc(sizeof(*(data->rs_resp)) + 8, GFP_KERNEL);575 if (!data->rs_resp) {576 res = -ENOMEM;577 goto alloc_resp_err;578 }579 580 /* Find sensors */581 res = aem1_find_sensors(data);582 if (res)583 goto sensor_err;584 585 /* Add to our list of AEM devices */586 list_add_tail(&data->list, &driver_data.aem_devices);587 588 dev_info(data->ipmi.bmc_device, "Found AEM v%d.%d at 0x%X\n",589 data->ver_major, data->ver_minor,590 data->module_handle);591 return 0;592 593sensor_err:594 kfree(data->rs_resp);595alloc_resp_err:596 hwmon_device_unregister(data->hwmon_dev);597hwmon_reg_err:598 ipmi_destroy_user(data->ipmi.user);599ipmi_err:600 platform_set_drvdata(data->pdev, NULL);601 platform_device_del(data->pdev);602dev_add_err:603 platform_device_put(data->pdev);604dev_err:605 ida_free(&aem_ida, data->id);606id_err:607 kfree(data);608 609 return res;610}611 612/* Find and initialize all AEM1 instances */613static void aem_init_aem1(struct aem_ipmi_data *probe)614{615 int num, i, err;616 617 num = aem_find_aem1_count(probe);618 for (i = 0; i < num; i++) {619 err = aem_init_aem1_inst(probe, i);620 if (err) {621 dev_err(probe->bmc_device,622 "Error %d initializing AEM1 0x%X\n",623 err, i);624 }625 }626}627 628/* Probe functions for AEM2 devices */629 630/* Retrieve version and module handle for an AEM2 instance */631static int aem_find_aem2(struct aem_ipmi_data *data,632 struct aem_find_instance_resp *fi_resp,633 int instance_num)634{635 int res;636 struct aem_find_instance_req fi_req;637 638 fi_req.id = system_x_id;639 fi_req.instance_number = instance_num;640 fi_req.module_type_id = cpu_to_be16(AEM_MODULE_TYPE_ID);641 642 data->tx_message.cmd = AEM_FW_INSTANCE_CMD;643 data->tx_message.data = (char *)&fi_req;644 data->tx_message.data_len = sizeof(fi_req);645 646 data->rx_msg_data = fi_resp;647 data->rx_msg_len = sizeof(*fi_resp);648 649 aem_send_message(data);650 651 res = wait_for_completion_timeout(&data->read_complete, IPMI_TIMEOUT);652 if (!res)653 return -ETIMEDOUT;654 655 if (data->rx_result || data->rx_msg_len != sizeof(*fi_resp) ||656 memcmp(&fi_resp->id, &system_x_id, sizeof(system_x_id)) ||657 fi_resp->num_instances <= instance_num)658 return -ENOENT;659 660 return 0;661}662 663/* Find and initialize one AEM2 instance */664static int aem_init_aem2_inst(struct aem_ipmi_data *probe,665 struct aem_find_instance_resp *fi_resp)666{667 struct aem_data *data;668 int i;669 int res = -ENOMEM;670 671 data = kzalloc(sizeof(*data), GFP_KERNEL);672 if (!data)673 return res;674 mutex_init(&data->lock);675 676 /* Copy instance data */677 data->ver_major = fi_resp->major;678 data->ver_minor = fi_resp->minor;679 data->module_handle = fi_resp->module_handle;680 for (i = 0; i < AEM2_NUM_ENERGY_REGS; i++)681 data->power_period[i] = AEM_DEFAULT_POWER_INTERVAL;682 683 /* Create sub-device for this fw instance */684 data->id = ida_alloc(&aem_ida, GFP_KERNEL);685 if (data->id < 0)686 goto id_err;687 688 data->pdev = platform_device_alloc(DRVNAME, data->id);689 if (!data->pdev)690 goto dev_err;691 data->pdev->dev.driver = &aem_driver.driver;692 693 res = platform_device_add(data->pdev);694 if (res)695 goto dev_add_err;696 697 platform_set_drvdata(data->pdev, data);698 699 /* Set up IPMI interface */700 res = aem_init_ipmi_data(&data->ipmi, probe->interface,701 probe->bmc_device);702 if (res)703 goto ipmi_err;704 705 /* Register with hwmon */706 data->hwmon_dev = hwmon_device_register(&data->pdev->dev);707 if (IS_ERR(data->hwmon_dev)) {708 dev_err(&data->pdev->dev,709 "Unable to register hwmon device for IPMI interface %d\n",710 probe->interface);711 res = PTR_ERR(data->hwmon_dev);712 goto hwmon_reg_err;713 }714 715 data->update = update_aem2_sensors;716 data->rs_resp = kzalloc(sizeof(*(data->rs_resp)) + 8, GFP_KERNEL);717 if (!data->rs_resp) {718 res = -ENOMEM;719 goto alloc_resp_err;720 }721 722 /* Find sensors */723 res = aem2_find_sensors(data);724 if (res)725 goto sensor_err;726 727 /* Add to our list of AEM devices */728 list_add_tail(&data->list, &driver_data.aem_devices);729 730 dev_info(data->ipmi.bmc_device, "Found AEM v%d.%d at 0x%X\n",731 data->ver_major, data->ver_minor,732 data->module_handle);733 return 0;734 735sensor_err:736 kfree(data->rs_resp);737alloc_resp_err:738 hwmon_device_unregister(data->hwmon_dev);739hwmon_reg_err:740 ipmi_destroy_user(data->ipmi.user);741ipmi_err:742 platform_set_drvdata(data->pdev, NULL);743 platform_device_del(data->pdev);744dev_add_err:745 platform_device_put(data->pdev);746dev_err:747 ida_free(&aem_ida, data->id);748id_err:749 kfree(data);750 751 return res;752}753 754/* Find and initialize all AEM2 instances */755static void aem_init_aem2(struct aem_ipmi_data *probe)756{757 struct aem_find_instance_resp fi_resp;758 int err;759 int i = 0;760 761 while (!aem_find_aem2(probe, &fi_resp, i)) {762 if (fi_resp.major != 2) {763 dev_err(probe->bmc_device,764 "Unknown AEM v%d; please report this to the maintainer.\n",765 fi_resp.major);766 i++;767 continue;768 }769 err = aem_init_aem2_inst(probe, &fi_resp);770 if (err) {771 dev_err(probe->bmc_device,772 "Error %d initializing AEM2 0x%X\n",773 err, fi_resp.module_handle);774 }775 i++;776 }777}778 779/* Probe a BMC for AEM firmware instances */780static void aem_register_bmc(int iface, struct device *dev)781{782 struct aem_ipmi_data probe;783 784 if (aem_init_ipmi_data(&probe, iface, dev))785 return;786 787 /* Ignore probe errors; they won't cause problems */788 aem_init_aem1(&probe);789 aem_init_aem2(&probe);790 791 ipmi_destroy_user(probe.user);792}793 794/* Handle BMC deletion */795static void aem_bmc_gone(int iface)796{797 struct aem_data *p1, *next1;798 799 list_for_each_entry_safe(p1, next1, &driver_data.aem_devices, list)800 if (p1->ipmi.interface == iface)801 aem_delete(p1);802}803 804/* sysfs support functions */805 806/* AEM device name */807static ssize_t name_show(struct device *dev, struct device_attribute *devattr,808 char *buf)809{810 struct aem_data *data = dev_get_drvdata(dev);811 812 return sprintf(buf, "%s%d\n", DRVNAME, data->ver_major);813}814static SENSOR_DEVICE_ATTR_RO(name, name, 0);815 816/* AEM device version */817static ssize_t version_show(struct device *dev,818 struct device_attribute *devattr, char *buf)819{820 struct aem_data *data = dev_get_drvdata(dev);821 822 return sprintf(buf, "%d.%d\n", data->ver_major, data->ver_minor);823}824static SENSOR_DEVICE_ATTR_RO(version, version, 0);825 826/* Display power use */827static ssize_t aem_show_power(struct device *dev,828 struct device_attribute *devattr,829 char *buf)830{831 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);832 struct aem_data *data = dev_get_drvdata(dev);833 u64 before, after, delta, time;834 signed long leftover;835 836 mutex_lock(&data->lock);837 update_aem_energy_one(data, attr->index);838 time = ktime_get_ns();839 before = data->energy[attr->index];840 841 leftover = schedule_timeout_interruptible(842 msecs_to_jiffies(data->power_period[attr->index])843 );844 if (leftover) {845 mutex_unlock(&data->lock);846 return 0;847 }848 849 update_aem_energy_one(data, attr->index);850 time = ktime_get_ns() - time;851 after = data->energy[attr->index];852 mutex_unlock(&data->lock);853 854 delta = (after - before) * UJ_PER_MJ;855 856 return sprintf(buf, "%llu\n",857 (unsigned long long)div64_u64(delta * NSEC_PER_SEC, time));858}859 860/* Display energy use */861static ssize_t aem_show_energy(struct device *dev,862 struct device_attribute *devattr,863 char *buf)864{865 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);866 struct aem_data *a = dev_get_drvdata(dev);867 mutex_lock(&a->lock);868 update_aem_energy_one(a, attr->index);869 mutex_unlock(&a->lock);870 871 return sprintf(buf, "%llu\n",872 (unsigned long long)a->energy[attr->index] * 1000);873}874 875/* Display power interval registers */876static ssize_t aem_show_power_period(struct device *dev,877 struct device_attribute *devattr,878 char *buf)879{880 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);881 struct aem_data *a = dev_get_drvdata(dev);882 a->update(a);883 884 return sprintf(buf, "%lu\n", a->power_period[attr->index]);885}886 887/* Set power interval registers */888static ssize_t aem_set_power_period(struct device *dev,889 struct device_attribute *devattr,890 const char *buf, size_t count)891{892 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);893 struct aem_data *a = dev_get_drvdata(dev);894 unsigned long temp;895 int res;896 897 res = kstrtoul(buf, 10, &temp);898 if (res)899 return res;900 901 if (temp < AEM_MIN_POWER_INTERVAL)902 return -EINVAL;903 904 mutex_lock(&a->lock);905 a->power_period[attr->index] = temp;906 mutex_unlock(&a->lock);907 908 return count;909}910 911/* Discover sensors on an AEM device */912static int aem_register_sensors(struct aem_data *data,913 const struct aem_ro_sensor_template *ro,914 const struct aem_rw_sensor_template *rw)915{916 struct device *dev = &data->pdev->dev;917 struct sensor_device_attribute *sensors = data->sensors;918 int err;919 920 /* Set up read-only sensors */921 while (ro->label) {922 sysfs_attr_init(&sensors->dev_attr.attr);923 sensors->dev_attr.attr.name = ro->label;924 sensors->dev_attr.attr.mode = 0444;925 sensors->dev_attr.show = ro->show;926 sensors->index = ro->index;927 928 err = device_create_file(dev, &sensors->dev_attr);929 if (err) {930 sensors->dev_attr.attr.name = NULL;931 goto error;932 }933 sensors++;934 ro++;935 }936 937 /* Set up read-write sensors */938 while (rw->label) {939 sysfs_attr_init(&sensors->dev_attr.attr);940 sensors->dev_attr.attr.name = rw->label;941 sensors->dev_attr.attr.mode = 0644;942 sensors->dev_attr.show = rw->show;943 sensors->dev_attr.store = rw->set;944 sensors->index = rw->index;945 946 err = device_create_file(dev, &sensors->dev_attr);947 if (err) {948 sensors->dev_attr.attr.name = NULL;949 goto error;950 }951 sensors++;952 rw++;953 }954 955 err = device_create_file(dev, &sensor_dev_attr_name.dev_attr);956 if (err)957 goto error;958 err = device_create_file(dev, &sensor_dev_attr_version.dev_attr);959 return err;960 961error:962 aem_remove_sensors(data);963 return err;964}965 966/* sysfs support functions for AEM2 sensors */967 968/* Display temperature use */969static ssize_t aem2_show_temp(struct device *dev,970 struct device_attribute *devattr,971 char *buf)972{973 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);974 struct aem_data *a = dev_get_drvdata(dev);975 a->update(a);976 977 return sprintf(buf, "%u\n", a->temp[attr->index] * 1000);978}979 980/* Display power-capping registers */981static ssize_t aem2_show_pcap_value(struct device *dev,982 struct device_attribute *devattr,983 char *buf)984{985 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);986 struct aem_data *a = dev_get_drvdata(dev);987 a->update(a);988 989 return sprintf(buf, "%u\n", a->pcap[attr->index] * 100000);990}991 992/* Remove sensors attached to an AEM device */993static void aem_remove_sensors(struct aem_data *data)994{995 int i;996 997 for (i = 0; i < AEM_NUM_SENSORS; i++) {998 if (!data->sensors[i].dev_attr.attr.name)999 continue;1000 device_remove_file(&data->pdev->dev,1001 &data->sensors[i].dev_attr);1002 }1003 1004 device_remove_file(&data->pdev->dev,1005 &sensor_dev_attr_name.dev_attr);1006 device_remove_file(&data->pdev->dev,1007 &sensor_dev_attr_version.dev_attr);1008}1009 1010/* Sensor probe functions */1011 1012/* Description of AEM1 sensors */1013static const struct aem_ro_sensor_template aem1_ro_sensors[] = {1014{"energy1_input", aem_show_energy, 0},1015{"power1_average", aem_show_power, 0},1016{NULL, NULL, 0},1017};1018 1019static const struct aem_rw_sensor_template aem1_rw_sensors[] = {1020{"power1_average_interval", aem_show_power_period, aem_set_power_period, 0},1021{NULL, NULL, NULL, 0},1022};1023 1024/* Description of AEM2 sensors */1025static const struct aem_ro_sensor_template aem2_ro_sensors[] = {1026{"energy1_input", aem_show_energy, 0},1027{"energy2_input", aem_show_energy, 1},1028{"power1_average", aem_show_power, 0},1029{"power2_average", aem_show_power, 1},1030{"temp1_input", aem2_show_temp, 0},1031{"temp2_input", aem2_show_temp, 1},1032 1033{"power4_average", aem2_show_pcap_value, POWER_CAP_MAX_HOTPLUG},1034{"power5_average", aem2_show_pcap_value, POWER_CAP_MAX},1035{"power6_average", aem2_show_pcap_value, POWER_CAP_MIN_WARNING},1036{"power7_average", aem2_show_pcap_value, POWER_CAP_MIN},1037 1038{"power3_average", aem2_show_pcap_value, POWER_AUX},1039{"power_cap", aem2_show_pcap_value, POWER_CAP},1040{NULL, NULL, 0},1041};1042 1043static const struct aem_rw_sensor_template aem2_rw_sensors[] = {1044{"power1_average_interval", aem_show_power_period, aem_set_power_period, 0},1045{"power2_average_interval", aem_show_power_period, aem_set_power_period, 1},1046{NULL, NULL, NULL, 0},1047};1048 1049/* Set up AEM1 sensor attrs */1050static int aem1_find_sensors(struct aem_data *data)1051{1052 return aem_register_sensors(data, aem1_ro_sensors, aem1_rw_sensors);1053}1054 1055/* Set up AEM2 sensor attrs */1056static int aem2_find_sensors(struct aem_data *data)1057{1058 return aem_register_sensors(data, aem2_ro_sensors, aem2_rw_sensors);1059}1060 1061/* Module init/exit routines */1062 1063static int __init aem_init(void)1064{1065 int res;1066 1067 res = driver_register(&aem_driver.driver);1068 if (res) {1069 pr_err("Can't register aem driver\n");1070 return res;1071 }1072 1073 res = ipmi_smi_watcher_register(&driver_data.bmc_events);1074 if (res)1075 goto ipmi_reg_err;1076 return 0;1077 1078ipmi_reg_err:1079 driver_unregister(&aem_driver.driver);1080 return res;1081 1082}1083 1084static void __exit aem_exit(void)1085{1086 struct aem_data *p1, *next1;1087 1088 ipmi_smi_watcher_unregister(&driver_data.bmc_events);1089 driver_unregister(&aem_driver.driver);1090 list_for_each_entry_safe(p1, next1, &driver_data.aem_devices, list)1091 aem_delete(p1);1092}1093 1094MODULE_AUTHOR("Darrick J. Wong <darrick.wong@oracle.com>");1095MODULE_DESCRIPTION("IBM AEM power/temp/energy sensor driver");1096MODULE_LICENSE("GPL");1097 1098module_init(aem_init);1099module_exit(aem_exit);1100 1101MODULE_ALIAS("dmi:bvnIBM:*:pnIBMSystemx3350-*");1102MODULE_ALIAS("dmi:bvnIBM:*:pnIBMSystemx3550-*");1103MODULE_ALIAS("dmi:bvnIBM:*:pnIBMSystemx3650-*");1104MODULE_ALIAS("dmi:bvnIBM:*:pnIBMSystemx3655-*");1105MODULE_ALIAS("dmi:bvnIBM:*:pnIBMSystemx3755-*");1106MODULE_ALIAS("dmi:bvnIBM:*:pnIBM3850M2/x3950M2-*");1107MODULE_ALIAS("dmi:bvnIBM:*:pnIBMBladeHC10-*");1108