378 lines · c
1// SPDX-License-Identifier: GPL-2.02 3/*4 * IPMB driver to receive a request and send a response5 *6 * Copyright (C) 2019 Mellanox Techologies, Ltd.7 *8 * This was inspired by Brendan Higgins' ipmi-bmc-bt-i2c driver.9 */10 11#include <linux/acpi.h>12#include <linux/errno.h>13#include <linux/i2c.h>14#include <linux/miscdevice.h>15#include <linux/module.h>16#include <linux/mutex.h>17#include <linux/poll.h>18#include <linux/slab.h>19#include <linux/spinlock.h>20#include <linux/wait.h>21 22#define MAX_MSG_LEN 24023#define IPMB_REQUEST_LEN_MIN 724#define NETFN_RSP_BIT_MASK 0x425#define REQUEST_QUEUE_MAX_LEN 25626 27#define IPMB_MSG_LEN_IDX 028#define RQ_SA_8BIT_IDX 129#define NETFN_LUN_IDX 230 31#define GET_7BIT_ADDR(addr_8bit) (addr_8bit >> 1)32#define GET_8BIT_ADDR(addr_7bit) ((addr_7bit << 1) & 0xff)33 34#define IPMB_MSG_PAYLOAD_LEN_MAX (MAX_MSG_LEN - IPMB_REQUEST_LEN_MIN - 1)35 36#define SMBUS_MSG_HEADER_LENGTH 237#define SMBUS_MSG_IDX_OFFSET (SMBUS_MSG_HEADER_LENGTH + 1)38 39struct ipmb_msg {40 u8 len;41 u8 rs_sa;42 u8 netfn_rs_lun;43 u8 checksum1;44 u8 rq_sa;45 u8 rq_seq_rq_lun;46 u8 cmd;47 u8 payload[IPMB_MSG_PAYLOAD_LEN_MAX];48 /* checksum2 is included in payload */49} __packed;50 51struct ipmb_request_elem {52 struct list_head list;53 struct ipmb_msg request;54};55 56struct ipmb_dev {57 struct i2c_client *client;58 struct miscdevice miscdev;59 struct ipmb_msg request;60 struct list_head request_queue;61 atomic_t request_queue_len;62 size_t msg_idx;63 spinlock_t lock;64 wait_queue_head_t wait_queue;65 struct mutex file_mutex;66 bool is_i2c_protocol;67};68 69static inline struct ipmb_dev *to_ipmb_dev(struct file *file)70{71 return container_of(file->private_data, struct ipmb_dev, miscdev);72}73 74static ssize_t ipmb_read(struct file *file, char __user *buf, size_t count,75 loff_t *ppos)76{77 struct ipmb_dev *ipmb_dev = to_ipmb_dev(file);78 struct ipmb_request_elem *queue_elem;79 struct ipmb_msg msg;80 ssize_t ret = 0;81 82 memset(&msg, 0, sizeof(msg));83 84 spin_lock_irq(&ipmb_dev->lock);85 86 while (list_empty(&ipmb_dev->request_queue)) {87 spin_unlock_irq(&ipmb_dev->lock);88 89 if (file->f_flags & O_NONBLOCK)90 return -EAGAIN;91 92 ret = wait_event_interruptible(ipmb_dev->wait_queue,93 !list_empty(&ipmb_dev->request_queue));94 if (ret)95 return ret;96 97 spin_lock_irq(&ipmb_dev->lock);98 }99 100 queue_elem = list_first_entry(&ipmb_dev->request_queue,101 struct ipmb_request_elem, list);102 memcpy(&msg, &queue_elem->request, sizeof(msg));103 list_del(&queue_elem->list);104 kfree(queue_elem);105 atomic_dec(&ipmb_dev->request_queue_len);106 107 spin_unlock_irq(&ipmb_dev->lock);108 109 count = min_t(size_t, count, msg.len + 1);110 if (copy_to_user(buf, &msg, count))111 ret = -EFAULT;112 113 return ret < 0 ? ret : count;114}115 116static int ipmb_i2c_write(struct i2c_client *client, u8 *msg, u8 addr)117{118 struct i2c_msg i2c_msg;119 120 /*121 * subtract 1 byte (rq_sa) from the length of the msg passed to122 * raw i2c_transfer123 */124 i2c_msg.len = msg[IPMB_MSG_LEN_IDX] - 1;125 126 /* Assign message to buffer except first 2 bytes (length and address) */127 i2c_msg.buf = msg + 2;128 129 i2c_msg.addr = addr;130 i2c_msg.flags = client->flags & I2C_CLIENT_PEC;131 132 return i2c_transfer(client->adapter, &i2c_msg, 1);133}134 135static ssize_t ipmb_write(struct file *file, const char __user *buf,136 size_t count, loff_t *ppos)137{138 struct ipmb_dev *ipmb_dev = to_ipmb_dev(file);139 u8 rq_sa, netf_rq_lun, msg_len;140 struct i2c_client *temp_client;141 u8 msg[MAX_MSG_LEN];142 ssize_t ret;143 144 if (count > sizeof(msg))145 return -EINVAL;146 147 if (copy_from_user(&msg, buf, count))148 return -EFAULT;149 150 if (count < msg[0])151 return -EINVAL;152 153 rq_sa = GET_7BIT_ADDR(msg[RQ_SA_8BIT_IDX]);154 netf_rq_lun = msg[NETFN_LUN_IDX];155 156 /* Check i2c block transfer vs smbus */157 if (ipmb_dev->is_i2c_protocol) {158 ret = ipmb_i2c_write(ipmb_dev->client, msg, rq_sa);159 return (ret == 1) ? count : ret;160 }161 162 /*163 * subtract rq_sa and netf_rq_lun from the length of the msg. Fill the164 * temporary client. Note that its use is an exception for IPMI.165 */166 msg_len = msg[IPMB_MSG_LEN_IDX] - SMBUS_MSG_HEADER_LENGTH;167 temp_client = kmemdup(ipmb_dev->client, sizeof(*temp_client), GFP_KERNEL);168 if (!temp_client)169 return -ENOMEM;170 171 temp_client->addr = rq_sa;172 173 ret = i2c_smbus_write_block_data(temp_client, netf_rq_lun, msg_len,174 msg + SMBUS_MSG_IDX_OFFSET);175 kfree(temp_client);176 177 return ret < 0 ? ret : count;178}179 180static __poll_t ipmb_poll(struct file *file, poll_table *wait)181{182 struct ipmb_dev *ipmb_dev = to_ipmb_dev(file);183 __poll_t mask = EPOLLOUT;184 185 mutex_lock(&ipmb_dev->file_mutex);186 poll_wait(file, &ipmb_dev->wait_queue, wait);187 188 if (atomic_read(&ipmb_dev->request_queue_len))189 mask |= EPOLLIN;190 mutex_unlock(&ipmb_dev->file_mutex);191 192 return mask;193}194 195static const struct file_operations ipmb_fops = {196 .owner = THIS_MODULE,197 .read = ipmb_read,198 .write = ipmb_write,199 .poll = ipmb_poll,200};201 202/* Called with ipmb_dev->lock held. */203static void ipmb_handle_request(struct ipmb_dev *ipmb_dev)204{205 struct ipmb_request_elem *queue_elem;206 207 if (atomic_read(&ipmb_dev->request_queue_len) >=208 REQUEST_QUEUE_MAX_LEN)209 return;210 211 queue_elem = kmalloc(sizeof(*queue_elem), GFP_ATOMIC);212 if (!queue_elem)213 return;214 215 memcpy(&queue_elem->request, &ipmb_dev->request,216 sizeof(struct ipmb_msg));217 list_add(&queue_elem->list, &ipmb_dev->request_queue);218 atomic_inc(&ipmb_dev->request_queue_len);219 wake_up_all(&ipmb_dev->wait_queue);220}221 222static u8 ipmb_verify_checksum1(struct ipmb_dev *ipmb_dev, u8 rs_sa)223{224 /* The 8 lsb of the sum is 0 when the checksum is valid */225 return (rs_sa + ipmb_dev->request.netfn_rs_lun +226 ipmb_dev->request.checksum1);227}228 229/*230 * Verify if message has proper ipmb header with minimum length231 * and correct checksum byte.232 */233static bool is_ipmb_msg(struct ipmb_dev *ipmb_dev, u8 rs_sa)234{235 if ((ipmb_dev->msg_idx >= IPMB_REQUEST_LEN_MIN) &&236 (!ipmb_verify_checksum1(ipmb_dev, rs_sa)))237 return true;238 239 return false;240}241 242/*243 * The IPMB protocol only supports I2C Writes so there is no need244 * to support I2C_SLAVE_READ* events.245 * This i2c callback function only monitors IPMB request messages246 * and adds them in a queue, so that they can be handled by247 * receive_ipmb_request.248 */249static int ipmb_slave_cb(struct i2c_client *client,250 enum i2c_slave_event event, u8 *val)251{252 struct ipmb_dev *ipmb_dev = i2c_get_clientdata(client);253 u8 *buf = (u8 *)&ipmb_dev->request;254 unsigned long flags;255 256 spin_lock_irqsave(&ipmb_dev->lock, flags);257 switch (event) {258 case I2C_SLAVE_WRITE_REQUESTED:259 memset(&ipmb_dev->request, 0, sizeof(ipmb_dev->request));260 ipmb_dev->msg_idx = 0;261 262 /*263 * At index 0, ipmb_msg stores the length of msg,264 * skip it for now.265 * The len will be populated once the whole266 * buf is populated.267 *268 * The I2C bus driver's responsibility is to pass the269 * data bytes to the backend driver; it does not270 * forward the i2c slave address.271 * Since the first byte in the IPMB message is the272 * address of the responder, it is the responsibility273 * of the IPMB driver to format the message properly.274 * So this driver prepends the address of the responder275 * to the received i2c data before the request message276 * is handled in userland.277 */278 buf[++ipmb_dev->msg_idx] = GET_8BIT_ADDR(client->addr);279 break;280 281 case I2C_SLAVE_WRITE_RECEIVED:282 if (ipmb_dev->msg_idx >= sizeof(struct ipmb_msg) - 1)283 break;284 285 buf[++ipmb_dev->msg_idx] = *val;286 break;287 288 case I2C_SLAVE_STOP:289 ipmb_dev->request.len = ipmb_dev->msg_idx;290 if (is_ipmb_msg(ipmb_dev, GET_8BIT_ADDR(client->addr)))291 ipmb_handle_request(ipmb_dev);292 break;293 294 default:295 break;296 }297 spin_unlock_irqrestore(&ipmb_dev->lock, flags);298 299 return 0;300}301 302static int ipmb_probe(struct i2c_client *client)303{304 struct ipmb_dev *ipmb_dev;305 int ret;306 307 ipmb_dev = devm_kzalloc(&client->dev, sizeof(*ipmb_dev),308 GFP_KERNEL);309 if (!ipmb_dev)310 return -ENOMEM;311 312 spin_lock_init(&ipmb_dev->lock);313 init_waitqueue_head(&ipmb_dev->wait_queue);314 atomic_set(&ipmb_dev->request_queue_len, 0);315 INIT_LIST_HEAD(&ipmb_dev->request_queue);316 317 mutex_init(&ipmb_dev->file_mutex);318 319 ipmb_dev->miscdev.minor = MISC_DYNAMIC_MINOR;320 321 ipmb_dev->miscdev.name = devm_kasprintf(&client->dev, GFP_KERNEL,322 "%s%d", "ipmb-",323 client->adapter->nr);324 ipmb_dev->miscdev.fops = &ipmb_fops;325 ipmb_dev->miscdev.parent = &client->dev;326 ret = misc_register(&ipmb_dev->miscdev);327 if (ret)328 return ret;329 330 ipmb_dev->is_i2c_protocol331 = device_property_read_bool(&client->dev, "i2c-protocol");332 333 ipmb_dev->client = client;334 i2c_set_clientdata(client, ipmb_dev);335 ret = i2c_slave_register(client, ipmb_slave_cb);336 if (ret) {337 misc_deregister(&ipmb_dev->miscdev);338 return ret;339 }340 341 return 0;342}343 344static void ipmb_remove(struct i2c_client *client)345{346 struct ipmb_dev *ipmb_dev = i2c_get_clientdata(client);347 348 i2c_slave_unregister(client);349 misc_deregister(&ipmb_dev->miscdev);350}351 352static const struct i2c_device_id ipmb_id[] = {353 { "ipmb-dev" },354 {}355};356MODULE_DEVICE_TABLE(i2c, ipmb_id);357 358static const struct acpi_device_id acpi_ipmb_id[] = {359 { "IPMB0001", 0 },360 {},361};362MODULE_DEVICE_TABLE(acpi, acpi_ipmb_id);363 364static struct i2c_driver ipmb_driver = {365 .driver = {366 .name = "ipmb-dev",367 .acpi_match_table = ACPI_PTR(acpi_ipmb_id),368 },369 .probe = ipmb_probe,370 .remove = ipmb_remove,371 .id_table = ipmb_id,372};373module_i2c_driver(ipmb_driver);374 375MODULE_AUTHOR("Mellanox Technologies");376MODULE_DESCRIPTION("IPMB driver");377MODULE_LICENSE("GPL v2");378