569 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (c) 2015-2018, Intel Corporation.4 */5 6#define pr_fmt(fmt) "kcs-bmc: " fmt7 8#include <linux/errno.h>9#include <linux/io.h>10#include <linux/ipmi_bmc.h>11#include <linux/list.h>12#include <linux/miscdevice.h>13#include <linux/module.h>14#include <linux/mutex.h>15#include <linux/platform_device.h>16#include <linux/poll.h>17#include <linux/sched.h>18#include <linux/slab.h>19 20#include "kcs_bmc_client.h"21 22/* Different phases of the KCS BMC module.23 * KCS_PHASE_IDLE:24 * BMC should not be expecting nor sending any data.25 * KCS_PHASE_WRITE_START:26 * BMC is receiving a WRITE_START command from system software.27 * KCS_PHASE_WRITE_DATA:28 * BMC is receiving a data byte from system software.29 * KCS_PHASE_WRITE_END_CMD:30 * BMC is waiting a last data byte from system software.31 * KCS_PHASE_WRITE_DONE:32 * BMC has received the whole request from system software.33 * KCS_PHASE_WAIT_READ:34 * BMC is waiting the response from the upper IPMI service.35 * KCS_PHASE_READ:36 * BMC is transferring the response to system software.37 * KCS_PHASE_ABORT_ERROR1:38 * BMC is waiting error status request from system software.39 * KCS_PHASE_ABORT_ERROR2:40 * BMC is waiting for idle status afer error from system software.41 * KCS_PHASE_ERROR:42 * BMC has detected a protocol violation at the interface level.43 */44enum kcs_ipmi_phases {45 KCS_PHASE_IDLE,46 47 KCS_PHASE_WRITE_START,48 KCS_PHASE_WRITE_DATA,49 KCS_PHASE_WRITE_END_CMD,50 KCS_PHASE_WRITE_DONE,51 52 KCS_PHASE_WAIT_READ,53 KCS_PHASE_READ,54 55 KCS_PHASE_ABORT_ERROR1,56 KCS_PHASE_ABORT_ERROR2,57 KCS_PHASE_ERROR58};59 60/* IPMI 2.0 - Table 9-4, KCS Interface Status Codes */61enum kcs_ipmi_errors {62 KCS_NO_ERROR = 0x00,63 KCS_ABORTED_BY_COMMAND = 0x01,64 KCS_ILLEGAL_CONTROL_CODE = 0x02,65 KCS_LENGTH_ERROR = 0x06,66 KCS_UNSPECIFIED_ERROR = 0xFF67};68 69struct kcs_bmc_ipmi {70 struct list_head entry;71 72 struct kcs_bmc_client client;73 74 spinlock_t lock;75 76 enum kcs_ipmi_phases phase;77 enum kcs_ipmi_errors error;78 79 wait_queue_head_t queue;80 bool data_in_avail;81 int data_in_idx;82 u8 *data_in;83 84 int data_out_idx;85 int data_out_len;86 u8 *data_out;87 88 struct mutex mutex;89 u8 *kbuffer;90 91 struct miscdevice miscdev;92};93 94#define DEVICE_NAME "ipmi-kcs"95 96#define KCS_MSG_BUFSIZ 100097 98#define KCS_ZERO_DATA 099 100/* IPMI 2.0 - Table 9-1, KCS Interface Status Register Bits */101#define KCS_STATUS_STATE(state) (state << 6)102#define KCS_STATUS_STATE_MASK GENMASK(7, 6)103#define KCS_STATUS_CMD_DAT BIT(3)104#define KCS_STATUS_SMS_ATN BIT(2)105#define KCS_STATUS_IBF BIT(1)106#define KCS_STATUS_OBF BIT(0)107 108/* IPMI 2.0 - Table 9-2, KCS Interface State Bits */109enum kcs_states {110 IDLE_STATE = 0,111 READ_STATE = 1,112 WRITE_STATE = 2,113 ERROR_STATE = 3,114};115 116/* IPMI 2.0 - Table 9-3, KCS Interface Control Codes */117#define KCS_CMD_GET_STATUS_ABORT 0x60118#define KCS_CMD_WRITE_START 0x61119#define KCS_CMD_WRITE_END 0x62120#define KCS_CMD_READ_BYTE 0x68121 122static inline void set_state(struct kcs_bmc_ipmi *priv, u8 state)123{124 kcs_bmc_update_status(priv->client.dev, KCS_STATUS_STATE_MASK, KCS_STATUS_STATE(state));125}126 127static void kcs_bmc_ipmi_force_abort(struct kcs_bmc_ipmi *priv)128{129 set_state(priv, ERROR_STATE);130 kcs_bmc_read_data(priv->client.dev);131 kcs_bmc_write_data(priv->client.dev, KCS_ZERO_DATA);132 133 priv->phase = KCS_PHASE_ERROR;134 priv->data_in_avail = false;135 priv->data_in_idx = 0;136}137 138static void kcs_bmc_ipmi_handle_data(struct kcs_bmc_ipmi *priv)139{140 struct kcs_bmc_device *dev;141 u8 data;142 143 dev = priv->client.dev;144 145 switch (priv->phase) {146 case KCS_PHASE_WRITE_START:147 priv->phase = KCS_PHASE_WRITE_DATA;148 fallthrough;149 150 case KCS_PHASE_WRITE_DATA:151 if (priv->data_in_idx < KCS_MSG_BUFSIZ) {152 set_state(priv, WRITE_STATE);153 kcs_bmc_write_data(dev, KCS_ZERO_DATA);154 priv->data_in[priv->data_in_idx++] = kcs_bmc_read_data(dev);155 } else {156 kcs_bmc_ipmi_force_abort(priv);157 priv->error = KCS_LENGTH_ERROR;158 }159 break;160 161 case KCS_PHASE_WRITE_END_CMD:162 if (priv->data_in_idx < KCS_MSG_BUFSIZ) {163 set_state(priv, READ_STATE);164 priv->data_in[priv->data_in_idx++] = kcs_bmc_read_data(dev);165 priv->phase = KCS_PHASE_WRITE_DONE;166 priv->data_in_avail = true;167 wake_up_interruptible(&priv->queue);168 } else {169 kcs_bmc_ipmi_force_abort(priv);170 priv->error = KCS_LENGTH_ERROR;171 }172 break;173 174 case KCS_PHASE_READ:175 if (priv->data_out_idx == priv->data_out_len)176 set_state(priv, IDLE_STATE);177 178 data = kcs_bmc_read_data(dev);179 if (data != KCS_CMD_READ_BYTE) {180 set_state(priv, ERROR_STATE);181 kcs_bmc_write_data(dev, KCS_ZERO_DATA);182 break;183 }184 185 if (priv->data_out_idx == priv->data_out_len) {186 kcs_bmc_write_data(dev, KCS_ZERO_DATA);187 priv->phase = KCS_PHASE_IDLE;188 break;189 }190 191 kcs_bmc_write_data(dev, priv->data_out[priv->data_out_idx++]);192 break;193 194 case KCS_PHASE_ABORT_ERROR1:195 set_state(priv, READ_STATE);196 kcs_bmc_read_data(dev);197 kcs_bmc_write_data(dev, priv->error);198 priv->phase = KCS_PHASE_ABORT_ERROR2;199 break;200 201 case KCS_PHASE_ABORT_ERROR2:202 set_state(priv, IDLE_STATE);203 kcs_bmc_read_data(dev);204 kcs_bmc_write_data(dev, KCS_ZERO_DATA);205 priv->phase = KCS_PHASE_IDLE;206 break;207 208 default:209 kcs_bmc_ipmi_force_abort(priv);210 break;211 }212}213 214static void kcs_bmc_ipmi_handle_cmd(struct kcs_bmc_ipmi *priv)215{216 u8 cmd;217 218 set_state(priv, WRITE_STATE);219 kcs_bmc_write_data(priv->client.dev, KCS_ZERO_DATA);220 221 cmd = kcs_bmc_read_data(priv->client.dev);222 switch (cmd) {223 case KCS_CMD_WRITE_START:224 priv->phase = KCS_PHASE_WRITE_START;225 priv->error = KCS_NO_ERROR;226 priv->data_in_avail = false;227 priv->data_in_idx = 0;228 break;229 230 case KCS_CMD_WRITE_END:231 if (priv->phase != KCS_PHASE_WRITE_DATA) {232 kcs_bmc_ipmi_force_abort(priv);233 break;234 }235 236 priv->phase = KCS_PHASE_WRITE_END_CMD;237 break;238 239 case KCS_CMD_GET_STATUS_ABORT:240 if (priv->error == KCS_NO_ERROR)241 priv->error = KCS_ABORTED_BY_COMMAND;242 243 priv->phase = KCS_PHASE_ABORT_ERROR1;244 priv->data_in_avail = false;245 priv->data_in_idx = 0;246 break;247 248 default:249 kcs_bmc_ipmi_force_abort(priv);250 priv->error = KCS_ILLEGAL_CONTROL_CODE;251 break;252 }253}254 255static inline struct kcs_bmc_ipmi *client_to_kcs_bmc_ipmi(struct kcs_bmc_client *client)256{257 return container_of(client, struct kcs_bmc_ipmi, client);258}259 260static irqreturn_t kcs_bmc_ipmi_event(struct kcs_bmc_client *client)261{262 struct kcs_bmc_ipmi *priv;263 u8 status;264 int ret;265 266 priv = client_to_kcs_bmc_ipmi(client);267 if (!priv)268 return IRQ_NONE;269 270 spin_lock(&priv->lock);271 272 status = kcs_bmc_read_status(client->dev);273 if (status & KCS_STATUS_IBF) {274 if (status & KCS_STATUS_CMD_DAT)275 kcs_bmc_ipmi_handle_cmd(priv);276 else277 kcs_bmc_ipmi_handle_data(priv);278 279 ret = IRQ_HANDLED;280 } else {281 ret = IRQ_NONE;282 }283 284 spin_unlock(&priv->lock);285 286 return ret;287}288 289static const struct kcs_bmc_client_ops kcs_bmc_ipmi_client_ops = {290 .event = kcs_bmc_ipmi_event,291};292 293static inline struct kcs_bmc_ipmi *to_kcs_bmc(struct file *filp)294{295 return container_of(filp->private_data, struct kcs_bmc_ipmi, miscdev);296}297 298static int kcs_bmc_ipmi_open(struct inode *inode, struct file *filp)299{300 struct kcs_bmc_ipmi *priv = to_kcs_bmc(filp);301 302 return kcs_bmc_enable_device(priv->client.dev, &priv->client);303}304 305static __poll_t kcs_bmc_ipmi_poll(struct file *filp, poll_table *wait)306{307 struct kcs_bmc_ipmi *priv = to_kcs_bmc(filp);308 __poll_t mask = 0;309 310 poll_wait(filp, &priv->queue, wait);311 312 spin_lock_irq(&priv->lock);313 if (priv->data_in_avail)314 mask |= EPOLLIN;315 spin_unlock_irq(&priv->lock);316 317 return mask;318}319 320static ssize_t kcs_bmc_ipmi_read(struct file *filp, char __user *buf,321 size_t count, loff_t *ppos)322{323 struct kcs_bmc_ipmi *priv = to_kcs_bmc(filp);324 bool data_avail;325 size_t data_len;326 ssize_t ret;327 328 if (!(filp->f_flags & O_NONBLOCK))329 wait_event_interruptible(priv->queue,330 priv->data_in_avail);331 332 mutex_lock(&priv->mutex);333 334 spin_lock_irq(&priv->lock);335 data_avail = priv->data_in_avail;336 if (data_avail) {337 data_len = priv->data_in_idx;338 memcpy(priv->kbuffer, priv->data_in, data_len);339 }340 spin_unlock_irq(&priv->lock);341 342 if (!data_avail) {343 ret = -EAGAIN;344 goto out_unlock;345 }346 347 if (count < data_len) {348 pr_err("channel=%u with too large data : %zu\n",349 priv->client.dev->channel, data_len);350 351 spin_lock_irq(&priv->lock);352 kcs_bmc_ipmi_force_abort(priv);353 spin_unlock_irq(&priv->lock);354 355 ret = -EOVERFLOW;356 goto out_unlock;357 }358 359 if (copy_to_user(buf, priv->kbuffer, data_len)) {360 ret = -EFAULT;361 goto out_unlock;362 }363 364 ret = data_len;365 366 spin_lock_irq(&priv->lock);367 if (priv->phase == KCS_PHASE_WRITE_DONE) {368 priv->phase = KCS_PHASE_WAIT_READ;369 priv->data_in_avail = false;370 priv->data_in_idx = 0;371 } else {372 ret = -EAGAIN;373 }374 spin_unlock_irq(&priv->lock);375 376out_unlock:377 mutex_unlock(&priv->mutex);378 379 return ret;380}381 382static ssize_t kcs_bmc_ipmi_write(struct file *filp, const char __user *buf,383 size_t count, loff_t *ppos)384{385 struct kcs_bmc_ipmi *priv = to_kcs_bmc(filp);386 ssize_t ret;387 388 /* a minimum response size '3' : netfn + cmd + ccode */389 if (count < 3 || count > KCS_MSG_BUFSIZ)390 return -EINVAL;391 392 mutex_lock(&priv->mutex);393 394 if (copy_from_user(priv->kbuffer, buf, count)) {395 ret = -EFAULT;396 goto out_unlock;397 }398 399 spin_lock_irq(&priv->lock);400 if (priv->phase == KCS_PHASE_WAIT_READ) {401 priv->phase = KCS_PHASE_READ;402 priv->data_out_idx = 1;403 priv->data_out_len = count;404 memcpy(priv->data_out, priv->kbuffer, count);405 kcs_bmc_write_data(priv->client.dev, priv->data_out[0]);406 ret = count;407 } else {408 ret = -EINVAL;409 }410 spin_unlock_irq(&priv->lock);411 412out_unlock:413 mutex_unlock(&priv->mutex);414 415 return ret;416}417 418static long kcs_bmc_ipmi_ioctl(struct file *filp, unsigned int cmd,419 unsigned long arg)420{421 struct kcs_bmc_ipmi *priv = to_kcs_bmc(filp);422 long ret = 0;423 424 spin_lock_irq(&priv->lock);425 426 switch (cmd) {427 case IPMI_BMC_IOCTL_SET_SMS_ATN:428 kcs_bmc_update_status(priv->client.dev, KCS_STATUS_SMS_ATN, KCS_STATUS_SMS_ATN);429 break;430 431 case IPMI_BMC_IOCTL_CLEAR_SMS_ATN:432 kcs_bmc_update_status(priv->client.dev, KCS_STATUS_SMS_ATN, 0);433 break;434 435 case IPMI_BMC_IOCTL_FORCE_ABORT:436 kcs_bmc_ipmi_force_abort(priv);437 break;438 439 default:440 ret = -EINVAL;441 break;442 }443 444 spin_unlock_irq(&priv->lock);445 446 return ret;447}448 449static int kcs_bmc_ipmi_release(struct inode *inode, struct file *filp)450{451 struct kcs_bmc_ipmi *priv = to_kcs_bmc(filp);452 453 kcs_bmc_ipmi_force_abort(priv);454 kcs_bmc_disable_device(priv->client.dev, &priv->client);455 456 return 0;457}458 459static const struct file_operations kcs_bmc_ipmi_fops = {460 .owner = THIS_MODULE,461 .open = kcs_bmc_ipmi_open,462 .read = kcs_bmc_ipmi_read,463 .write = kcs_bmc_ipmi_write,464 .release = kcs_bmc_ipmi_release,465 .poll = kcs_bmc_ipmi_poll,466 .unlocked_ioctl = kcs_bmc_ipmi_ioctl,467};468 469static DEFINE_SPINLOCK(kcs_bmc_ipmi_instances_lock);470static LIST_HEAD(kcs_bmc_ipmi_instances);471 472static int kcs_bmc_ipmi_add_device(struct kcs_bmc_device *kcs_bmc)473{474 struct kcs_bmc_ipmi *priv;475 int rc;476 477 priv = devm_kzalloc(kcs_bmc->dev, sizeof(*priv), GFP_KERNEL);478 if (!priv)479 return -ENOMEM;480 481 spin_lock_init(&priv->lock);482 mutex_init(&priv->mutex);483 484 init_waitqueue_head(&priv->queue);485 486 priv->client.dev = kcs_bmc;487 priv->client.ops = &kcs_bmc_ipmi_client_ops;488 priv->data_in = devm_kmalloc(kcs_bmc->dev, KCS_MSG_BUFSIZ, GFP_KERNEL);489 priv->data_out = devm_kmalloc(kcs_bmc->dev, KCS_MSG_BUFSIZ, GFP_KERNEL);490 priv->kbuffer = devm_kmalloc(kcs_bmc->dev, KCS_MSG_BUFSIZ, GFP_KERNEL);491 492 priv->miscdev.minor = MISC_DYNAMIC_MINOR;493 priv->miscdev.name = devm_kasprintf(kcs_bmc->dev, GFP_KERNEL, "%s%u", DEVICE_NAME,494 kcs_bmc->channel);495 if (!priv->data_in || !priv->data_out || !priv->kbuffer || !priv->miscdev.name)496 return -EINVAL;497 498 priv->miscdev.fops = &kcs_bmc_ipmi_fops;499 500 rc = misc_register(&priv->miscdev);501 if (rc) {502 dev_err(kcs_bmc->dev, "Unable to register device: %d\n", rc);503 return rc;504 }505 506 spin_lock_irq(&kcs_bmc_ipmi_instances_lock);507 list_add(&priv->entry, &kcs_bmc_ipmi_instances);508 spin_unlock_irq(&kcs_bmc_ipmi_instances_lock);509 510 dev_info(kcs_bmc->dev, "Initialised IPMI client for channel %d", kcs_bmc->channel);511 512 return 0;513}514 515static int kcs_bmc_ipmi_remove_device(struct kcs_bmc_device *kcs_bmc)516{517 struct kcs_bmc_ipmi *priv = NULL, *pos;518 519 spin_lock_irq(&kcs_bmc_ipmi_instances_lock);520 list_for_each_entry(pos, &kcs_bmc_ipmi_instances, entry) {521 if (pos->client.dev == kcs_bmc) {522 priv = pos;523 list_del(&pos->entry);524 break;525 }526 }527 spin_unlock_irq(&kcs_bmc_ipmi_instances_lock);528 529 if (!priv)530 return -ENODEV;531 532 misc_deregister(&priv->miscdev);533 kcs_bmc_disable_device(priv->client.dev, &priv->client);534 devm_kfree(kcs_bmc->dev, priv->kbuffer);535 devm_kfree(kcs_bmc->dev, priv->data_out);536 devm_kfree(kcs_bmc->dev, priv->data_in);537 devm_kfree(kcs_bmc->dev, priv);538 539 return 0;540}541 542static const struct kcs_bmc_driver_ops kcs_bmc_ipmi_driver_ops = {543 .add_device = kcs_bmc_ipmi_add_device,544 .remove_device = kcs_bmc_ipmi_remove_device,545};546 547static struct kcs_bmc_driver kcs_bmc_ipmi_driver = {548 .ops = &kcs_bmc_ipmi_driver_ops,549};550 551static int __init kcs_bmc_ipmi_init(void)552{553 kcs_bmc_register_driver(&kcs_bmc_ipmi_driver);554 555 return 0;556}557module_init(kcs_bmc_ipmi_init);558 559static void __exit kcs_bmc_ipmi_exit(void)560{561 kcs_bmc_unregister_driver(&kcs_bmc_ipmi_driver);562}563module_exit(kcs_bmc_ipmi_exit);564 565MODULE_LICENSE("GPL v2");566MODULE_AUTHOR("Haiyue Wang <haiyue.wang@linux.intel.com>");567MODULE_AUTHOR("Andrew Jeffery <andrew@aj.id.au>");568MODULE_DESCRIPTION("KCS BMC to handle the IPMI request from system software");569