^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 PowerExecutive temperature/power sensors
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) 2007 IBM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Author: Darrick J. Wong <darrick.wong@oracle.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/ipmi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/hwmon.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/hwmon-sysfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/jiffies.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #define REFRESH_INTERVAL (2 * HZ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #define DRVNAME "ibmpex"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define PEX_GET_VERSION 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define PEX_GET_SENSOR_COUNT 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define PEX_GET_SENSOR_NAME 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define PEX_RESET_HIGH_LOW 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define PEX_GET_SENSOR_DATA 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define PEX_NET_FUNCTION 0x3A
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define PEX_COMMAND 0x3C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) static inline u16 extract_value(const char *data, int offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) return be16_to_cpup((__be16 *)&data[offset]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define TEMP_SENSOR 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define POWER_SENSOR 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define PEX_SENSOR_TYPE_LEN 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) static u8 const power_sensor_sig[] = {0x70, 0x77, 0x72};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) static u8 const temp_sensor_sig[] = {0x74, 0x65, 0x6D};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define PEX_MULT_LEN 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) static u8 const watt_sensor_sig[] = {0x41, 0x43};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define PEX_NUM_SENSOR_FUNCS 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) static const char * const sensor_name_suffixes[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) "_lowest",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) "_highest"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) static void ibmpex_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) static void ibmpex_register_bmc(int iface, struct device *dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) static void ibmpex_bmc_gone(int iface);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) struct ibmpex_sensor_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) int in_use;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) s16 values[PEX_NUM_SENSOR_FUNCS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) int multiplier;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) struct sensor_device_attribute_2 attr[PEX_NUM_SENSOR_FUNCS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) struct ibmpex_bmc_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) struct list_head list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) struct device *hwmon_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) struct device *bmc_device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) struct mutex lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) char valid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) unsigned long last_updated; /* In jiffies */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) struct ipmi_addr address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) struct completion read_complete;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) struct ipmi_user *user;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) int interface;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) struct kernel_ipmi_msg tx_message;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) unsigned char tx_msg_data[IPMI_MAX_MSG_LENGTH];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) long tx_msgid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) unsigned char rx_msg_data[IPMI_MAX_MSG_LENGTH];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) unsigned long rx_msg_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) unsigned char rx_result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) int rx_recv_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) unsigned char sensor_major;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) unsigned char sensor_minor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) unsigned char num_sensors;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) struct ibmpex_sensor_data *sensors;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) struct ibmpex_driver_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) struct list_head bmc_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) struct ipmi_smi_watcher bmc_events;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) struct ipmi_user_hndl ipmi_hndlrs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) static struct ibmpex_driver_data driver_data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) .bmc_data = LIST_HEAD_INIT(driver_data.bmc_data),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) .bmc_events = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) .new_smi = ibmpex_register_bmc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) .smi_gone = ibmpex_bmc_gone,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) .ipmi_hndlrs = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) .ipmi_recv_hndl = ibmpex_msg_handler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) static int ibmpex_send_message(struct ibmpex_bmc_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) err = ipmi_validate_addr(&data->address, sizeof(data->address));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) data->tx_msgid++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) err = ipmi_request_settime(data->user, &data->address, data->tx_msgid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) &data->tx_message, data, 0, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) goto out1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) out1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) dev_err(data->bmc_device, "request_settime=%x\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) dev_err(data->bmc_device, "validate_addr=%x\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) static int ibmpex_ver_check(struct ibmpex_bmc_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) data->tx_msg_data[0] = PEX_GET_VERSION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) data->tx_message.data_len = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) ibmpex_send_message(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) wait_for_completion(&data->read_complete);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) if (data->rx_result || data->rx_msg_len != 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) data->sensor_major = data->rx_msg_data[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) data->sensor_minor = data->rx_msg_data[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) dev_info(data->bmc_device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) "Found BMC with sensor interface v%d.%d %d-%02d-%02d on interface %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) data->sensor_major,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) data->sensor_minor,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) extract_value(data->rx_msg_data, 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) data->rx_msg_data[4],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) data->rx_msg_data[5],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) data->interface);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) static int ibmpex_query_sensor_count(struct ibmpex_bmc_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) data->tx_msg_data[0] = PEX_GET_SENSOR_COUNT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) data->tx_message.data_len = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) ibmpex_send_message(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) wait_for_completion(&data->read_complete);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) if (data->rx_result || data->rx_msg_len != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) return data->rx_msg_data[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) static int ibmpex_query_sensor_name(struct ibmpex_bmc_data *data, int sensor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) data->tx_msg_data[0] = PEX_GET_SENSOR_NAME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) data->tx_msg_data[1] = sensor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) data->tx_message.data_len = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) ibmpex_send_message(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) wait_for_completion(&data->read_complete);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) if (data->rx_result || data->rx_msg_len < 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) static int ibmpex_query_sensor_data(struct ibmpex_bmc_data *data, int sensor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) data->tx_msg_data[0] = PEX_GET_SENSOR_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) data->tx_msg_data[1] = sensor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) data->tx_message.data_len = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) ibmpex_send_message(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) wait_for_completion(&data->read_complete);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) if (data->rx_result || data->rx_msg_len < 26) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) dev_err(data->bmc_device, "Error reading sensor %d.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) sensor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) static int ibmpex_reset_high_low_data(struct ibmpex_bmc_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) data->tx_msg_data[0] = PEX_RESET_HIGH_LOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) data->tx_message.data_len = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) ibmpex_send_message(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) wait_for_completion(&data->read_complete);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) static void ibmpex_update_device(struct ibmpex_bmc_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) int i, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) mutex_lock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) if (time_before(jiffies, data->last_updated + REFRESH_INTERVAL) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) data->valid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) for (i = 0; i < data->num_sensors; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) if (!data->sensors[i].in_use)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) err = ibmpex_query_sensor_data(data, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) data->sensors[i].values[0] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) extract_value(data->rx_msg_data, 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) data->sensors[i].values[1] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) extract_value(data->rx_msg_data, 18);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) data->sensors[i].values[2] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) extract_value(data->rx_msg_data, 20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) data->last_updated = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) data->valid = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) mutex_unlock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) static struct ibmpex_bmc_data *get_bmc_data(int iface)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) struct ibmpex_bmc_data *p, *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) list_for_each_entry_safe(p, next, &driver_data.bmc_data, list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) if (p->interface == iface)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) return p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) static ssize_t name_show(struct device *dev, struct device_attribute *devattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) return sprintf(buf, "%s\n", DRVNAME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) static SENSOR_DEVICE_ATTR_RO(name, name, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) static ssize_t ibmpex_show_sensor(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) struct device_attribute *devattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) struct ibmpex_bmc_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) int mult = data->sensors[attr->index].multiplier;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) ibmpex_update_device(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) return sprintf(buf, "%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) data->sensors[attr->index].values[attr->nr] * mult);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) static ssize_t ibmpex_high_low_store(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) struct device_attribute *devattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) struct ibmpex_bmc_data *data = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) ibmpex_reset_high_low_data(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) static SENSOR_DEVICE_ATTR_WO(reset_high_low, ibmpex_high_low, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) static int is_power_sensor(const char *sensor_id, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) if (len < PEX_SENSOR_TYPE_LEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) if (!memcmp(sensor_id, power_sensor_sig, PEX_SENSOR_TYPE_LEN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) static int is_temp_sensor(const char *sensor_id, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) if (len < PEX_SENSOR_TYPE_LEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) if (!memcmp(sensor_id, temp_sensor_sig, PEX_SENSOR_TYPE_LEN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) return 0;
^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) static int power_sensor_multiplier(struct ibmpex_bmc_data *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) const char *sensor_id, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) if (data->sensor_major == 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) return 1000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) for (i = PEX_SENSOR_TYPE_LEN; i < len - 1; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) if (!memcmp(&sensor_id[i], watt_sensor_sig, PEX_MULT_LEN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) return 1000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) return 100000;
^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) static int create_sensor(struct ibmpex_bmc_data *data, int type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) int counter, int sensor, int func)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) char *n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) n = kmalloc(32, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) if (!n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) if (type == TEMP_SENSOR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) sprintf(n, "temp%d_input%s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) counter, sensor_name_suffixes[func]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) else if (type == POWER_SENSOR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) sprintf(n, "power%d_average%s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) counter, sensor_name_suffixes[func]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) sysfs_attr_init(&data->sensors[sensor].attr[func].dev_attr.attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) data->sensors[sensor].attr[func].dev_attr.attr.name = n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) data->sensors[sensor].attr[func].dev_attr.attr.mode = 0444;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) data->sensors[sensor].attr[func].dev_attr.show = ibmpex_show_sensor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) data->sensors[sensor].attr[func].index = sensor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) data->sensors[sensor].attr[func].nr = func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) err = device_create_file(data->bmc_device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) &data->sensors[sensor].attr[func].dev_attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) data->sensors[sensor].attr[func].dev_attr.attr.name = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) kfree(n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) static int ibmpex_find_sensors(struct ibmpex_bmc_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) int i, j, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) int sensor_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) int sensor_counter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) int num_power = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) int num_temp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) err = ibmpex_query_sensor_count(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) if (err <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) data->num_sensors = err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) data->sensors = kcalloc(data->num_sensors, sizeof(*data->sensors),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) if (!data->sensors)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) for (i = 0; i < data->num_sensors; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) err = ibmpex_query_sensor_name(data, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) if (is_power_sensor(data->rx_msg_data, data->rx_msg_len)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) sensor_type = POWER_SENSOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) num_power++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) sensor_counter = num_power;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) data->sensors[i].multiplier =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) power_sensor_multiplier(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) data->rx_msg_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) data->rx_msg_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) } else if (is_temp_sensor(data->rx_msg_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) data->rx_msg_len)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) sensor_type = TEMP_SENSOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) num_temp++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) sensor_counter = num_temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) data->sensors[i].multiplier = 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) data->sensors[i].in_use = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) /* Create attributes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) for (j = 0; j < PEX_NUM_SENSOR_FUNCS; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) err = create_sensor(data, sensor_type, sensor_counter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) i, j);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) goto exit_remove;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) err = device_create_file(data->bmc_device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) &sensor_dev_attr_reset_high_low.dev_attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) goto exit_remove;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) err = device_create_file(data->bmc_device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) &sensor_dev_attr_name.dev_attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) goto exit_remove;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) exit_remove:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) device_remove_file(data->bmc_device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) &sensor_dev_attr_reset_high_low.dev_attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) device_remove_file(data->bmc_device, &sensor_dev_attr_name.dev_attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) for (i = 0; i < data->num_sensors; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) for (j = 0; j < PEX_NUM_SENSOR_FUNCS; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) if (!data->sensors[i].attr[j].dev_attr.attr.name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) device_remove_file(data->bmc_device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) &data->sensors[i].attr[j].dev_attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) kfree(data->sensors[i].attr[j].dev_attr.attr.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) kfree(data->sensors);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) static void ibmpex_register_bmc(int iface, struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) struct ibmpex_bmc_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) data = kzalloc(sizeof(*data), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) if (!data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) data->address.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) data->address.channel = IPMI_BMC_CHANNEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) data->address.data[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) data->interface = iface;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) data->bmc_device = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) /* Create IPMI messaging interface user */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) err = ipmi_create_user(data->interface, &driver_data.ipmi_hndlrs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) data, &data->user);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) dev_err(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) "Unable to register user with IPMI interface %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) data->interface);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) mutex_init(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) /* Initialize message */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) data->tx_msgid = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) init_completion(&data->read_complete);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) data->tx_message.netfn = PEX_NET_FUNCTION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) data->tx_message.cmd = PEX_COMMAND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) data->tx_message.data = data->tx_msg_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) /* Does this BMC support PowerExecutive? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) err = ibmpex_ver_check(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) goto out_user;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) /* Register the BMC as a HWMON class device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) data->hwmon_dev = hwmon_device_register(data->bmc_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) if (IS_ERR(data->hwmon_dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) dev_err(data->bmc_device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) "Unable to register hwmon device for IPMI interface %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) data->interface);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) goto out_user;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) /* finally add the new bmc data to the bmc data list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) dev_set_drvdata(dev, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) list_add_tail(&data->list, &driver_data.bmc_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) /* Now go find all the sensors */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) err = ibmpex_find_sensors(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) dev_err(data->bmc_device, "Error %d finding sensors\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) goto out_register;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) out_register:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) hwmon_device_unregister(data->hwmon_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) out_user:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) ipmi_destroy_user(data->user);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) kfree(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) static void ibmpex_bmc_delete(struct ibmpex_bmc_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) int i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) device_remove_file(data->bmc_device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) &sensor_dev_attr_reset_high_low.dev_attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) device_remove_file(data->bmc_device, &sensor_dev_attr_name.dev_attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) for (i = 0; i < data->num_sensors; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) for (j = 0; j < PEX_NUM_SENSOR_FUNCS; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) if (!data->sensors[i].attr[j].dev_attr.attr.name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) device_remove_file(data->bmc_device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) &data->sensors[i].attr[j].dev_attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) kfree(data->sensors[i].attr[j].dev_attr.attr.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) list_del(&data->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) dev_set_drvdata(data->bmc_device, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) hwmon_device_unregister(data->hwmon_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) ipmi_destroy_user(data->user);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) kfree(data->sensors);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) kfree(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) static void ibmpex_bmc_gone(int iface)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) struct ibmpex_bmc_data *data = get_bmc_data(iface);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) if (!data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) ibmpex_bmc_delete(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) static void ibmpex_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) struct ibmpex_bmc_data *data = (struct ibmpex_bmc_data *)user_msg_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) if (msg->msgid != data->tx_msgid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) dev_err(data->bmc_device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) "Mismatch between received msgid (%02x) and transmitted msgid (%02x)!\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) (int)msg->msgid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) (int)data->tx_msgid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) ipmi_free_recv_msg(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) data->rx_recv_type = msg->recv_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) if (msg->msg.data_len > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) data->rx_result = msg->msg.data[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) data->rx_result = IPMI_UNKNOWN_ERR_COMPLETION_CODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) if (msg->msg.data_len > 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) data->rx_msg_len = msg->msg.data_len - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) memcpy(data->rx_msg_data, msg->msg.data + 1, data->rx_msg_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) data->rx_msg_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) ipmi_free_recv_msg(msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) complete(&data->read_complete);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) static int __init ibmpex_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) return ipmi_smi_watcher_register(&driver_data.bmc_events);
^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) static void __exit ibmpex_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) struct ibmpex_bmc_data *p, *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) ipmi_smi_watcher_unregister(&driver_data.bmc_events);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) list_for_each_entry_safe(p, next, &driver_data.bmc_data, list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) ibmpex_bmc_delete(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) MODULE_AUTHOR("Darrick J. Wong <darrick.wong@oracle.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) MODULE_DESCRIPTION("IBM PowerExecutive power/temperature sensor driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) module_init(ibmpex_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) module_exit(ibmpex_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) MODULE_ALIAS("dmi:bvnIBM:*:pnIBMSystemx3350-*");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) MODULE_ALIAS("dmi:bvnIBM:*:pnIBMSystemx3550-*");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) MODULE_ALIAS("dmi:bvnIBM:*:pnIBMSystemx3650-*");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) MODULE_ALIAS("dmi:bvnIBM:*:pnIBMSystemx3655-*");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) MODULE_ALIAS("dmi:bvnIBM:*:pnIBMSystemx3755-*");