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