1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Miscellaneous character driver for ChromeOS Embedded Controller 4 * 5 * Copyright 2014 Google, Inc. 6 * Copyright 2019 Google LLC 7 * 8 * This file is a rework and part of the code is ported from 9 * drivers/mfd/cros_ec_dev.c that was originally written by 10 * Bill Richardson. 11 */ 12 13 #include <linux/init.h> 14 #include <linux/device.h> 15 #include <linux/fs.h> 16 #include <linux/kref.h> 17 #include <linux/miscdevice.h> 18 #include <linux/module.h> 19 #include <linux/notifier.h> 20 #include <linux/platform_data/cros_ec_chardev.h> 21 #include <linux/platform_data/cros_ec_commands.h> 22 #include <linux/platform_data/cros_ec_proto.h> 23 #include <linux/platform_device.h> 24 #include <linux/poll.h> 25 #include <linux/rwsem.h> 26 #include <linux/slab.h> 27 #include <linux/types.h> 28 #include <linux/uaccess.h> 29 30 #define DRV_NAME "cros-ec-chardev" 31 32 /* Arbitrary bounded size for the event queue */ 33 #define CROS_MAX_EVENT_LEN PAGE_SIZE 34 35 /* 36 * Platform device driver data. 37 */ 38 struct chardev_pdata { 39 struct miscdevice misc; 40 struct kref kref; 41 struct rw_semaphore ec_dev_sem; 42 struct cros_ec_device *ec_dev; 43 u16 cmd_offset; 44 struct blocking_notifier_head subscribers; 45 struct notifier_block relay; 46 }; 47 48 static void chardev_pdata_release(struct kref *kref) 49 { 50 struct chardev_pdata *pdata = container_of(kref, typeof(*pdata), kref); 51 52 kfree(pdata); 53 } 54 55 static int cros_ec_chardev_relay_event(struct notifier_block *nb, 56 unsigned long queued_during_suspend, 57 void *_notify) 58 { 59 struct chardev_pdata *pdata = container_of(nb, typeof(*pdata), relay); 60 61 blocking_notifier_call_chain(&pdata->subscribers, queued_during_suspend, 62 _notify); 63 return NOTIFY_OK; 64 } 65 66 struct chardev_priv { 67 struct notifier_block notifier; 68 wait_queue_head_t wait_event; 69 unsigned long event_mask; 70 struct list_head events; 71 size_t event_len; 72 struct chardev_pdata *pdata; 73 }; 74 75 struct ec_event { 76 struct list_head node; 77 size_t size; 78 u8 event_type; 79 u8 data[]; 80 }; 81 82 static int ec_get_version(struct chardev_priv *priv, char *str, int maxlen) 83 { 84 static const char * const current_image_name[] = { 85 "unknown", "read-only", "read-write", "invalid", 86 }; 87 struct ec_response_get_version *resp; 88 struct cros_ec_command *msg; 89 int ret; 90 91 msg = kzalloc(sizeof(*msg) + sizeof(*resp), GFP_KERNEL); 92 if (!msg) 93 return -ENOMEM; 94 95 msg->command = EC_CMD_GET_VERSION + priv->pdata->cmd_offset; 96 msg->insize = sizeof(*resp); 97 98 ret = cros_ec_cmd_xfer_status(priv->pdata->ec_dev, msg); 99 if (ret < 0) { 100 snprintf(str, maxlen, 101 "Unknown EC version, returned error: %d\n", 102 msg->result); 103 goto exit; 104 } 105 106 resp = (struct ec_response_get_version *)msg->data; 107 if (resp->current_image >= ARRAY_SIZE(current_image_name)) 108 resp->current_image = 3; /* invalid */ 109 110 snprintf(str, maxlen, "%s\n%s\n%s\n%s\n", CROS_EC_DEV_VERSION, 111 resp->version_string_ro, resp->version_string_rw, 112 current_image_name[resp->current_image]); 113 114 ret = 0; 115 exit: 116 kfree(msg); 117 return ret; 118 } 119 120 static int cros_ec_chardev_mkbp_event(struct notifier_block *nb, 121 unsigned long queued_during_suspend, 122 void *_notify) 123 { 124 struct chardev_priv *priv = container_of(nb, struct chardev_priv, 125 notifier); 126 struct cros_ec_device *ec_dev; 127 struct ec_event *event; 128 unsigned long event_bit; 129 int total_size; 130 131 guard(rwsem_read)(&priv->pdata->ec_dev_sem); 132 if (!priv->pdata->ec_dev) 133 return NOTIFY_DONE; 134 ec_dev = priv->pdata->ec_dev; 135 136 event_bit = 1 << ec_dev->event_data.event_type; 137 total_size = sizeof(*event) + ec_dev->event_size; 138 139 if (!(event_bit & priv->event_mask) || 140 (priv->event_len + total_size) > CROS_MAX_EVENT_LEN) 141 return NOTIFY_DONE; 142 143 event = kzalloc(total_size, GFP_KERNEL); 144 if (!event) 145 return NOTIFY_DONE; 146 147 event->size = ec_dev->event_size; 148 event->event_type = ec_dev->event_data.event_type; 149 memcpy(event->data, &ec_dev->event_data.data, ec_dev->event_size); 150 151 spin_lock(&priv->wait_event.lock); 152 list_add_tail(&event->node, &priv->events); 153 priv->event_len += total_size; 154 wake_up_locked(&priv->wait_event); 155 spin_unlock(&priv->wait_event.lock); 156 157 return NOTIFY_OK; 158 } 159 160 static struct ec_event *cros_ec_chardev_fetch_event(struct chardev_priv *priv, 161 bool fetch, bool block) 162 { 163 struct ec_event *event; 164 int err; 165 166 spin_lock(&priv->wait_event.lock); 167 if (!block && list_empty(&priv->events)) { 168 event = ERR_PTR(-EWOULDBLOCK); 169 goto out; 170 } 171 172 if (!fetch) { 173 event = NULL; 174 goto out; 175 } 176 177 err = wait_event_interruptible_locked(priv->wait_event, 178 !list_empty(&priv->events)); 179 if (err) { 180 event = ERR_PTR(err); 181 goto out; 182 } 183 184 event = list_first_entry(&priv->events, struct ec_event, node); 185 list_del(&event->node); 186 priv->event_len -= sizeof(*event) + event->size; 187 188 out: 189 spin_unlock(&priv->wait_event.lock); 190 return event; 191 } 192 193 /* 194 * Device file ops 195 */ 196 static int cros_ec_chardev_open(struct inode *inode, struct file *filp) 197 { 198 struct miscdevice *mdev = filp->private_data; 199 struct chardev_pdata *pdata = container_of(mdev, typeof(*pdata), misc); 200 struct chardev_priv *priv; 201 int ret; 202 203 priv = kzalloc_obj(*priv); 204 if (!priv) 205 return -ENOMEM; 206 207 priv->pdata = pdata; 208 kref_get(&pdata->kref); 209 filp->private_data = priv; 210 INIT_LIST_HEAD(&priv->events); 211 init_waitqueue_head(&priv->wait_event); 212 nonseekable_open(inode, filp); 213 214 priv->notifier.notifier_call = cros_ec_chardev_mkbp_event; 215 ret = blocking_notifier_chain_register(&pdata->subscribers, 216 &priv->notifier); 217 if (ret) { 218 dev_err(pdata->ec_dev->dev, 219 "failed to register event notifier\n"); 220 kref_put(&priv->pdata->kref, chardev_pdata_release); 221 kfree(priv); 222 } 223 224 return ret; 225 } 226 227 static __poll_t cros_ec_chardev_poll(struct file *filp, poll_table *wait) 228 { 229 struct chardev_priv *priv = filp->private_data; 230 231 guard(rwsem_read)(&priv->pdata->ec_dev_sem); 232 if (!priv->pdata->ec_dev) 233 return EPOLLHUP; 234 235 poll_wait(filp, &priv->wait_event, wait); 236 237 if (list_empty(&priv->events)) 238 return 0; 239 240 return EPOLLIN | EPOLLRDNORM; 241 } 242 243 static ssize_t cros_ec_chardev_read(struct file *filp, char __user *buffer, 244 size_t length, loff_t *offset) 245 { 246 char msg[sizeof(struct ec_response_get_version) + 247 sizeof(CROS_EC_DEV_VERSION)]; 248 struct chardev_priv *priv = filp->private_data; 249 size_t count; 250 int ret; 251 252 guard(rwsem_read)(&priv->pdata->ec_dev_sem); 253 if (!priv->pdata->ec_dev) 254 return -ENODEV; 255 256 if (priv->event_mask) { /* queued MKBP event */ 257 struct ec_event *event; 258 259 event = cros_ec_chardev_fetch_event(priv, length != 0, 260 !(filp->f_flags & O_NONBLOCK)); 261 if (IS_ERR(event)) 262 return PTR_ERR(event); 263 /* 264 * length == 0 is special - no IO is done but we check 265 * for error conditions. 266 */ 267 if (length == 0) 268 return 0; 269 270 /* The event is 1 byte of type plus the payload */ 271 count = min(length, event->size + 1); 272 ret = copy_to_user(buffer, &event->event_type, count); 273 kfree(event); 274 if (ret) /* the copy failed */ 275 return -EFAULT; 276 *offset = count; 277 return count; 278 } 279 280 /* 281 * Legacy behavior if no event mask is defined 282 */ 283 if (*offset != 0) 284 return 0; 285 286 ret = ec_get_version(priv, msg, sizeof(msg)); 287 if (ret) 288 return ret; 289 290 count = min(length, strlen(msg)); 291 292 if (copy_to_user(buffer, msg, count)) 293 return -EFAULT; 294 295 *offset = count; 296 return count; 297 } 298 299 static int cros_ec_chardev_release(struct inode *inode, struct file *filp) 300 { 301 struct chardev_priv *priv = filp->private_data; 302 struct ec_event *event, *e; 303 304 blocking_notifier_chain_unregister(&priv->pdata->subscribers, 305 &priv->notifier); 306 kref_put(&priv->pdata->kref, chardev_pdata_release); 307 308 list_for_each_entry_safe(event, e, &priv->events, node) { 309 list_del(&event->node); 310 kfree(event); 311 } 312 kfree(priv); 313 314 return 0; 315 } 316 317 /* 318 * Ioctls 319 */ 320 static long cros_ec_chardev_ioctl_xcmd(struct chardev_priv *priv, void __user *arg) 321 { 322 struct cros_ec_command *s_cmd; 323 struct cros_ec_command u_cmd; 324 long ret; 325 326 if (copy_from_user(&u_cmd, arg, sizeof(u_cmd))) 327 return -EFAULT; 328 329 if (u_cmd.outsize > EC_MAX_MSG_BYTES || 330 u_cmd.insize > EC_MAX_MSG_BYTES) 331 return -EINVAL; 332 333 s_cmd = kzalloc(sizeof(*s_cmd) + max(u_cmd.outsize, u_cmd.insize), 334 GFP_KERNEL); 335 if (!s_cmd) 336 return -ENOMEM; 337 338 if (copy_from_user(s_cmd, arg, sizeof(*s_cmd) + u_cmd.outsize)) { 339 ret = -EFAULT; 340 goto exit; 341 } 342 343 if (u_cmd.outsize != s_cmd->outsize || 344 u_cmd.insize != s_cmd->insize) { 345 ret = -EINVAL; 346 goto exit; 347 } 348 349 s_cmd->command += priv->pdata->cmd_offset; 350 ret = cros_ec_cmd_xfer(priv->pdata->ec_dev, s_cmd); 351 /* Only copy data to userland if data was received. */ 352 if (ret < 0) 353 goto exit; 354 355 if (copy_to_user(arg, s_cmd, sizeof(*s_cmd) + s_cmd->insize)) 356 ret = -EFAULT; 357 exit: 358 kfree(s_cmd); 359 return ret; 360 } 361 362 static long cros_ec_chardev_ioctl_readmem(struct chardev_priv *priv, void __user *arg) 363 { 364 struct cros_ec_device *ec_dev = priv->pdata->ec_dev; 365 struct cros_ec_readmem s_mem = { }; 366 long num; 367 368 /* Not every platform supports direct reads */ 369 if (!ec_dev->cmd_readmem) 370 return -ENOTTY; 371 372 if (copy_from_user(&s_mem, arg, sizeof(s_mem))) 373 return -EFAULT; 374 375 if (s_mem.bytes > sizeof(s_mem.buffer)) 376 return -EINVAL; 377 378 num = ec_dev->cmd_readmem(ec_dev, s_mem.offset, s_mem.bytes, 379 s_mem.buffer); 380 if (num <= 0) 381 return num; 382 383 if (copy_to_user((void __user *)arg, &s_mem, sizeof(s_mem))) 384 return -EFAULT; 385 386 return num; 387 } 388 389 static long cros_ec_chardev_ioctl(struct file *filp, unsigned int cmd, 390 unsigned long arg) 391 { 392 struct chardev_priv *priv = filp->private_data; 393 394 guard(rwsem_read)(&priv->pdata->ec_dev_sem); 395 if (!priv->pdata->ec_dev) 396 return -ENODEV; 397 398 if (_IOC_TYPE(cmd) != CROS_EC_DEV_IOC) 399 return -ENOTTY; 400 401 switch (cmd) { 402 case CROS_EC_DEV_IOCXCMD: 403 return cros_ec_chardev_ioctl_xcmd(priv, (void __user *)arg); 404 case CROS_EC_DEV_IOCRDMEM: 405 return cros_ec_chardev_ioctl_readmem(priv, (void __user *)arg); 406 case CROS_EC_DEV_IOCEVENTMASK: 407 priv->event_mask = arg; 408 return 0; 409 } 410 411 return -ENOTTY; 412 } 413 414 static const struct file_operations chardev_fops = { 415 .open = cros_ec_chardev_open, 416 .poll = cros_ec_chardev_poll, 417 .read = cros_ec_chardev_read, 418 .release = cros_ec_chardev_release, 419 .unlocked_ioctl = cros_ec_chardev_ioctl, 420 #ifdef CONFIG_COMPAT 421 .compat_ioctl = cros_ec_chardev_ioctl, 422 #endif 423 }; 424 425 static int cros_ec_chardev_probe(struct platform_device *pdev) 426 { 427 struct cros_ec_dev *ec = dev_get_drvdata(pdev->dev.parent); 428 struct cros_ec_platform *ec_platform = dev_get_platdata(ec->dev); 429 struct chardev_pdata *pdata; 430 int ret; 431 432 pdata = kzalloc_obj(*pdata); 433 if (!pdata) 434 return -ENOMEM; 435 436 platform_set_drvdata(pdev, pdata); 437 kref_init(&pdata->kref); 438 init_rwsem(&pdata->ec_dev_sem); 439 pdata->ec_dev = ec->ec_dev; 440 pdata->cmd_offset = ec->cmd_offset; 441 BLOCKING_INIT_NOTIFIER_HEAD(&pdata->subscribers); 442 pdata->relay.notifier_call = cros_ec_chardev_relay_event; 443 ret = blocking_notifier_chain_register(&pdata->ec_dev->event_notifier, 444 &pdata->relay); 445 if (ret) { 446 dev_err(&pdev->dev, "failed to register event notifier\n"); 447 goto err_put_pdata; 448 } 449 450 pdata->misc.minor = MISC_DYNAMIC_MINOR; 451 pdata->misc.fops = &chardev_fops; 452 pdata->misc.name = ec_platform->ec_name; 453 pdata->misc.parent = pdev->dev.parent; 454 455 ret = misc_register(&pdata->misc); 456 if (ret) { 457 dev_err(&pdev->dev, "failed to register misc device\n"); 458 goto err_unregister_notifier; 459 } 460 461 return 0; 462 err_unregister_notifier: 463 blocking_notifier_chain_unregister(&pdata->ec_dev->event_notifier, 464 &pdata->relay); 465 err_put_pdata: 466 kref_put(&pdata->kref, chardev_pdata_release); 467 return ret; 468 } 469 470 static void cros_ec_chardev_remove(struct platform_device *pdev) 471 { 472 struct chardev_pdata *pdata = platform_get_drvdata(pdev); 473 struct cros_ec_device *ec_dev = pdata->ec_dev; 474 475 /* stop new fops from being created */ 476 misc_deregister(&pdata->misc); 477 /* stop existing fops from running */ 478 scoped_guard(rwsem_write, &pdata->ec_dev_sem) 479 pdata->ec_dev = NULL; 480 481 blocking_notifier_chain_unregister(&ec_dev->event_notifier, 482 &pdata->relay); 483 kref_put(&pdata->kref, chardev_pdata_release); 484 } 485 486 static const struct platform_device_id cros_ec_chardev_id[] = { 487 { DRV_NAME, 0 }, 488 {} 489 }; 490 MODULE_DEVICE_TABLE(platform, cros_ec_chardev_id); 491 492 static struct platform_driver cros_ec_chardev_driver = { 493 .driver = { 494 .name = DRV_NAME, 495 }, 496 .probe = cros_ec_chardev_probe, 497 .remove = cros_ec_chardev_remove, 498 .id_table = cros_ec_chardev_id, 499 }; 500 501 module_platform_driver(cros_ec_chardev_driver); 502 503 MODULE_AUTHOR("Enric Balletbo i Serra <enric.balletbo@collabora.com>"); 504 MODULE_DESCRIPTION("ChromeOS EC Miscellaneous Character Driver"); 505 MODULE_LICENSE("GPL"); 506