brintos

brintos / linux-shallow public Read only

0
0
Text · 26.4 KiB · 157e232 Raw
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