mei_wdt.c (14969B)
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Intel Management Engine Interface (Intel MEI) Linux driver 4 * Copyright (c) 2015, Intel Corporation. 5 */ 6 7#include <linux/module.h> 8#include <linux/slab.h> 9#include <linux/interrupt.h> 10#include <linux/debugfs.h> 11#include <linux/completion.h> 12#include <linux/watchdog.h> 13 14#include <linux/uuid.h> 15#include <linux/mei_cl_bus.h> 16 17/* 18 * iAMT Watchdog Device 19 */ 20#define INTEL_AMT_WATCHDOG_ID "iamt_wdt" 21 22#define MEI_WDT_DEFAULT_TIMEOUT 120 /* seconds */ 23#define MEI_WDT_MIN_TIMEOUT 120 /* seconds */ 24#define MEI_WDT_MAX_TIMEOUT 65535 /* seconds */ 25 26/* Commands */ 27#define MEI_MANAGEMENT_CONTROL 0x02 28 29/* MEI Management Control version number */ 30#define MEI_MC_VERSION_NUMBER 0x10 31 32/* Sub Commands */ 33#define MEI_MC_START_WD_TIMER_REQ 0x13 34#define MEI_MC_START_WD_TIMER_RES 0x83 35#define MEI_WDT_STATUS_SUCCESS 0 36#define MEI_WDT_WDSTATE_NOT_REQUIRED 0x1 37#define MEI_MC_STOP_WD_TIMER_REQ 0x14 38 39/** 40 * enum mei_wdt_state - internal watchdog state 41 * 42 * @MEI_WDT_PROBE: wd in probing stage 43 * @MEI_WDT_IDLE: wd is idle and not opened 44 * @MEI_WDT_START: wd was opened, start was called 45 * @MEI_WDT_RUNNING: wd is expecting keep alive pings 46 * @MEI_WDT_STOPPING: wd is stopping and will move to IDLE 47 * @MEI_WDT_NOT_REQUIRED: wd device is not required 48 */ 49enum mei_wdt_state { 50 MEI_WDT_PROBE, 51 MEI_WDT_IDLE, 52 MEI_WDT_START, 53 MEI_WDT_RUNNING, 54 MEI_WDT_STOPPING, 55 MEI_WDT_NOT_REQUIRED, 56}; 57 58static const char *mei_wdt_state_str(enum mei_wdt_state state) 59{ 60 switch (state) { 61 case MEI_WDT_PROBE: 62 return "PROBE"; 63 case MEI_WDT_IDLE: 64 return "IDLE"; 65 case MEI_WDT_START: 66 return "START"; 67 case MEI_WDT_RUNNING: 68 return "RUNNING"; 69 case MEI_WDT_STOPPING: 70 return "STOPPING"; 71 case MEI_WDT_NOT_REQUIRED: 72 return "NOT_REQUIRED"; 73 default: 74 return "unknown"; 75 } 76} 77 78/** 79 * struct mei_wdt - mei watchdog driver 80 * @wdd: watchdog device 81 * 82 * @cldev: mei watchdog client device 83 * @state: watchdog internal state 84 * @resp_required: ping required response 85 * @response: ping response completion 86 * @unregister: unregister worker 87 * @reg_lock: watchdog device registration lock 88 * @timeout: watchdog current timeout 89 * 90 * @dbgfs_dir: debugfs dir entry 91 */ 92struct mei_wdt { 93 struct watchdog_device wdd; 94 95 struct mei_cl_device *cldev; 96 enum mei_wdt_state state; 97 bool resp_required; 98 struct completion response; 99 struct work_struct unregister; 100 struct mutex reg_lock; 101 u16 timeout; 102 103#if IS_ENABLED(CONFIG_DEBUG_FS) 104 struct dentry *dbgfs_dir; 105#endif /* CONFIG_DEBUG_FS */ 106}; 107 108/** 109 * struct mei_mc_hdr - Management Control Command Header 110 * 111 * @command: Management Control (0x2) 112 * @bytecount: Number of bytes in the message beyond this byte 113 * @subcommand: Management Control Subcommand 114 * @versionnumber: Management Control Version (0x10) 115 */ 116struct mei_mc_hdr { 117 u8 command; 118 u8 bytecount; 119 u8 subcommand; 120 u8 versionnumber; 121}; 122 123/** 124 * struct mei_wdt_start_request - watchdog start/ping 125 * 126 * @hdr: Management Control Command Header 127 * @timeout: timeout value 128 * @reserved: reserved (legacy) 129 */ 130struct mei_wdt_start_request { 131 struct mei_mc_hdr hdr; 132 u16 timeout; 133 u8 reserved[17]; 134} __packed; 135 136/** 137 * struct mei_wdt_start_response - watchdog start/ping response 138 * 139 * @hdr: Management Control Command Header 140 * @status: operation status 141 * @wdstate: watchdog status bit mask 142 */ 143struct mei_wdt_start_response { 144 struct mei_mc_hdr hdr; 145 u8 status; 146 u8 wdstate; 147} __packed; 148 149/** 150 * struct mei_wdt_stop_request - watchdog stop 151 * 152 * @hdr: Management Control Command Header 153 */ 154struct mei_wdt_stop_request { 155 struct mei_mc_hdr hdr; 156} __packed; 157 158/** 159 * mei_wdt_ping - send wd start/ping command 160 * 161 * @wdt: mei watchdog device 162 * 163 * Return: 0 on success, 164 * negative errno code on failure 165 */ 166static int mei_wdt_ping(struct mei_wdt *wdt) 167{ 168 struct mei_wdt_start_request req; 169 const size_t req_len = sizeof(req); 170 int ret; 171 172 memset(&req, 0, req_len); 173 req.hdr.command = MEI_MANAGEMENT_CONTROL; 174 req.hdr.bytecount = req_len - offsetof(struct mei_mc_hdr, subcommand); 175 req.hdr.subcommand = MEI_MC_START_WD_TIMER_REQ; 176 req.hdr.versionnumber = MEI_MC_VERSION_NUMBER; 177 req.timeout = wdt->timeout; 178 179 ret = mei_cldev_send(wdt->cldev, (u8 *)&req, req_len); 180 if (ret < 0) 181 return ret; 182 183 return 0; 184} 185 186/** 187 * mei_wdt_stop - send wd stop command 188 * 189 * @wdt: mei watchdog device 190 * 191 * Return: 0 on success, 192 * negative errno code on failure 193 */ 194static int mei_wdt_stop(struct mei_wdt *wdt) 195{ 196 struct mei_wdt_stop_request req; 197 const size_t req_len = sizeof(req); 198 int ret; 199 200 memset(&req, 0, req_len); 201 req.hdr.command = MEI_MANAGEMENT_CONTROL; 202 req.hdr.bytecount = req_len - offsetof(struct mei_mc_hdr, subcommand); 203 req.hdr.subcommand = MEI_MC_STOP_WD_TIMER_REQ; 204 req.hdr.versionnumber = MEI_MC_VERSION_NUMBER; 205 206 ret = mei_cldev_send(wdt->cldev, (u8 *)&req, req_len); 207 if (ret < 0) 208 return ret; 209 210 return 0; 211} 212 213/** 214 * mei_wdt_ops_start - wd start command from the watchdog core. 215 * 216 * @wdd: watchdog device 217 * 218 * Return: 0 on success or -ENODEV; 219 */ 220static int mei_wdt_ops_start(struct watchdog_device *wdd) 221{ 222 struct mei_wdt *wdt = watchdog_get_drvdata(wdd); 223 224 wdt->state = MEI_WDT_START; 225 wdd->timeout = wdt->timeout; 226 return 0; 227} 228 229/** 230 * mei_wdt_ops_stop - wd stop command from the watchdog core. 231 * 232 * @wdd: watchdog device 233 * 234 * Return: 0 if success, negative errno code for failure 235 */ 236static int mei_wdt_ops_stop(struct watchdog_device *wdd) 237{ 238 struct mei_wdt *wdt = watchdog_get_drvdata(wdd); 239 int ret; 240 241 if (wdt->state != MEI_WDT_RUNNING) 242 return 0; 243 244 wdt->state = MEI_WDT_STOPPING; 245 246 ret = mei_wdt_stop(wdt); 247 if (ret) 248 return ret; 249 250 wdt->state = MEI_WDT_IDLE; 251 252 return 0; 253} 254 255/** 256 * mei_wdt_ops_ping - wd ping command from the watchdog core. 257 * 258 * @wdd: watchdog device 259 * 260 * Return: 0 if success, negative errno code on failure 261 */ 262static int mei_wdt_ops_ping(struct watchdog_device *wdd) 263{ 264 struct mei_wdt *wdt = watchdog_get_drvdata(wdd); 265 int ret; 266 267 if (wdt->state != MEI_WDT_START && wdt->state != MEI_WDT_RUNNING) 268 return 0; 269 270 if (wdt->resp_required) 271 init_completion(&wdt->response); 272 273 wdt->state = MEI_WDT_RUNNING; 274 ret = mei_wdt_ping(wdt); 275 if (ret) 276 return ret; 277 278 if (wdt->resp_required) 279 ret = wait_for_completion_killable(&wdt->response); 280 281 return ret; 282} 283 284/** 285 * mei_wdt_ops_set_timeout - wd set timeout command from the watchdog core. 286 * 287 * @wdd: watchdog device 288 * @timeout: timeout value to set 289 * 290 * Return: 0 if success, negative errno code for failure 291 */ 292static int mei_wdt_ops_set_timeout(struct watchdog_device *wdd, 293 unsigned int timeout) 294{ 295 296 struct mei_wdt *wdt = watchdog_get_drvdata(wdd); 297 298 /* valid value is already checked by the caller */ 299 wdt->timeout = timeout; 300 wdd->timeout = timeout; 301 302 return 0; 303} 304 305static const struct watchdog_ops wd_ops = { 306 .owner = THIS_MODULE, 307 .start = mei_wdt_ops_start, 308 .stop = mei_wdt_ops_stop, 309 .ping = mei_wdt_ops_ping, 310 .set_timeout = mei_wdt_ops_set_timeout, 311}; 312 313/* not const as the firmware_version field need to be retrieved */ 314static struct watchdog_info wd_info = { 315 .identity = INTEL_AMT_WATCHDOG_ID, 316 .options = WDIOF_KEEPALIVEPING | 317 WDIOF_SETTIMEOUT | 318 WDIOF_ALARMONLY, 319}; 320 321/** 322 * __mei_wdt_is_registered - check if wdt is registered 323 * 324 * @wdt: mei watchdog device 325 * 326 * Return: true if the wdt is registered with the watchdog subsystem 327 * Locking: should be called under wdt->reg_lock 328 */ 329static inline bool __mei_wdt_is_registered(struct mei_wdt *wdt) 330{ 331 return !!watchdog_get_drvdata(&wdt->wdd); 332} 333 334/** 335 * mei_wdt_unregister - unregister from the watchdog subsystem 336 * 337 * @wdt: mei watchdog device 338 */ 339static void mei_wdt_unregister(struct mei_wdt *wdt) 340{ 341 mutex_lock(&wdt->reg_lock); 342 343 if (__mei_wdt_is_registered(wdt)) { 344 watchdog_unregister_device(&wdt->wdd); 345 watchdog_set_drvdata(&wdt->wdd, NULL); 346 memset(&wdt->wdd, 0, sizeof(wdt->wdd)); 347 } 348 349 mutex_unlock(&wdt->reg_lock); 350} 351 352/** 353 * mei_wdt_register - register with the watchdog subsystem 354 * 355 * @wdt: mei watchdog device 356 * 357 * Return: 0 if success, negative errno code for failure 358 */ 359static int mei_wdt_register(struct mei_wdt *wdt) 360{ 361 struct device *dev; 362 int ret; 363 364 if (!wdt || !wdt->cldev) 365 return -EINVAL; 366 367 dev = &wdt->cldev->dev; 368 369 mutex_lock(&wdt->reg_lock); 370 371 if (__mei_wdt_is_registered(wdt)) { 372 ret = 0; 373 goto out; 374 } 375 376 wdt->wdd.info = &wd_info; 377 wdt->wdd.ops = &wd_ops; 378 wdt->wdd.parent = dev; 379 wdt->wdd.timeout = MEI_WDT_DEFAULT_TIMEOUT; 380 wdt->wdd.min_timeout = MEI_WDT_MIN_TIMEOUT; 381 wdt->wdd.max_timeout = MEI_WDT_MAX_TIMEOUT; 382 383 watchdog_set_drvdata(&wdt->wdd, wdt); 384 watchdog_stop_on_reboot(&wdt->wdd); 385 watchdog_stop_on_unregister(&wdt->wdd); 386 387 ret = watchdog_register_device(&wdt->wdd); 388 if (ret) 389 watchdog_set_drvdata(&wdt->wdd, NULL); 390 391 wdt->state = MEI_WDT_IDLE; 392 393out: 394 mutex_unlock(&wdt->reg_lock); 395 return ret; 396} 397 398static void mei_wdt_unregister_work(struct work_struct *work) 399{ 400 struct mei_wdt *wdt = container_of(work, struct mei_wdt, unregister); 401 402 mei_wdt_unregister(wdt); 403} 404 405/** 406 * mei_wdt_rx - callback for data receive 407 * 408 * @cldev: bus device 409 */ 410static void mei_wdt_rx(struct mei_cl_device *cldev) 411{ 412 struct mei_wdt *wdt = mei_cldev_get_drvdata(cldev); 413 struct mei_wdt_start_response res; 414 const size_t res_len = sizeof(res); 415 int ret; 416 417 ret = mei_cldev_recv(wdt->cldev, (u8 *)&res, res_len); 418 if (ret < 0) { 419 dev_err(&cldev->dev, "failure in recv %d\n", ret); 420 return; 421 } 422 423 /* Empty response can be sent on stop */ 424 if (ret == 0) 425 return; 426 427 if (ret < sizeof(struct mei_mc_hdr)) { 428 dev_err(&cldev->dev, "recv small data %d\n", ret); 429 return; 430 } 431 432 if (res.hdr.command != MEI_MANAGEMENT_CONTROL || 433 res.hdr.versionnumber != MEI_MC_VERSION_NUMBER) { 434 dev_err(&cldev->dev, "wrong command received\n"); 435 return; 436 } 437 438 if (res.hdr.subcommand != MEI_MC_START_WD_TIMER_RES) { 439 dev_warn(&cldev->dev, "unsupported command %d :%s[%d]\n", 440 res.hdr.subcommand, 441 mei_wdt_state_str(wdt->state), 442 wdt->state); 443 return; 444 } 445 446 /* Run the unregistration in a worker as this can be 447 * run only after ping completion, otherwise the flow will 448 * deadlock on watchdog core mutex. 449 */ 450 if (wdt->state == MEI_WDT_RUNNING) { 451 if (res.wdstate & MEI_WDT_WDSTATE_NOT_REQUIRED) { 452 wdt->state = MEI_WDT_NOT_REQUIRED; 453 schedule_work(&wdt->unregister); 454 } 455 goto out; 456 } 457 458 if (wdt->state == MEI_WDT_PROBE) { 459 if (res.wdstate & MEI_WDT_WDSTATE_NOT_REQUIRED) { 460 wdt->state = MEI_WDT_NOT_REQUIRED; 461 } else { 462 /* stop the watchdog and register watchdog device */ 463 mei_wdt_stop(wdt); 464 mei_wdt_register(wdt); 465 } 466 return; 467 } 468 469 dev_warn(&cldev->dev, "not in correct state %s[%d]\n", 470 mei_wdt_state_str(wdt->state), wdt->state); 471 472out: 473 if (!completion_done(&wdt->response)) 474 complete(&wdt->response); 475} 476 477/** 478 * mei_wdt_notif - callback for event notification 479 * 480 * @cldev: bus device 481 */ 482static void mei_wdt_notif(struct mei_cl_device *cldev) 483{ 484 struct mei_wdt *wdt = mei_cldev_get_drvdata(cldev); 485 486 if (wdt->state != MEI_WDT_NOT_REQUIRED) 487 return; 488 489 mei_wdt_register(wdt); 490} 491 492#if IS_ENABLED(CONFIG_DEBUG_FS) 493 494static ssize_t mei_dbgfs_read_activation(struct file *file, char __user *ubuf, 495 size_t cnt, loff_t *ppos) 496{ 497 struct mei_wdt *wdt = file->private_data; 498 const size_t bufsz = 32; 499 char buf[32]; 500 ssize_t pos; 501 502 mutex_lock(&wdt->reg_lock); 503 pos = scnprintf(buf, bufsz, "%s\n", 504 __mei_wdt_is_registered(wdt) ? "activated" : "deactivated"); 505 mutex_unlock(&wdt->reg_lock); 506 507 return simple_read_from_buffer(ubuf, cnt, ppos, buf, pos); 508} 509 510static const struct file_operations dbgfs_fops_activation = { 511 .open = simple_open, 512 .read = mei_dbgfs_read_activation, 513 .llseek = generic_file_llseek, 514}; 515 516static ssize_t mei_dbgfs_read_state(struct file *file, char __user *ubuf, 517 size_t cnt, loff_t *ppos) 518{ 519 struct mei_wdt *wdt = file->private_data; 520 char buf[32]; 521 ssize_t pos; 522 523 pos = scnprintf(buf, sizeof(buf), "state: %s\n", 524 mei_wdt_state_str(wdt->state)); 525 526 return simple_read_from_buffer(ubuf, cnt, ppos, buf, pos); 527} 528 529static const struct file_operations dbgfs_fops_state = { 530 .open = simple_open, 531 .read = mei_dbgfs_read_state, 532 .llseek = generic_file_llseek, 533}; 534 535static void dbgfs_unregister(struct mei_wdt *wdt) 536{ 537 debugfs_remove_recursive(wdt->dbgfs_dir); 538 wdt->dbgfs_dir = NULL; 539} 540 541static void dbgfs_register(struct mei_wdt *wdt) 542{ 543 struct dentry *dir; 544 545 dir = debugfs_create_dir(KBUILD_MODNAME, NULL); 546 wdt->dbgfs_dir = dir; 547 548 debugfs_create_file("state", S_IRUSR, dir, wdt, &dbgfs_fops_state); 549 550 debugfs_create_file("activation", S_IRUSR, dir, wdt, 551 &dbgfs_fops_activation); 552} 553 554#else 555 556static inline void dbgfs_unregister(struct mei_wdt *wdt) {} 557static inline void dbgfs_register(struct mei_wdt *wdt) {} 558#endif /* CONFIG_DEBUG_FS */ 559 560static int mei_wdt_probe(struct mei_cl_device *cldev, 561 const struct mei_cl_device_id *id) 562{ 563 struct mei_wdt *wdt; 564 int ret; 565 566 wdt = kzalloc(sizeof(struct mei_wdt), GFP_KERNEL); 567 if (!wdt) 568 return -ENOMEM; 569 570 wdt->timeout = MEI_WDT_DEFAULT_TIMEOUT; 571 wdt->state = MEI_WDT_PROBE; 572 wdt->cldev = cldev; 573 wdt->resp_required = mei_cldev_ver(cldev) > 0x1; 574 mutex_init(&wdt->reg_lock); 575 init_completion(&wdt->response); 576 INIT_WORK(&wdt->unregister, mei_wdt_unregister_work); 577 578 mei_cldev_set_drvdata(cldev, wdt); 579 580 ret = mei_cldev_enable(cldev); 581 if (ret < 0) { 582 dev_err(&cldev->dev, "Could not enable cl device\n"); 583 goto err_out; 584 } 585 586 ret = mei_cldev_register_rx_cb(wdt->cldev, mei_wdt_rx); 587 if (ret) { 588 dev_err(&cldev->dev, "Could not reg rx event ret=%d\n", ret); 589 goto err_disable; 590 } 591 592 ret = mei_cldev_register_notif_cb(wdt->cldev, mei_wdt_notif); 593 /* on legacy devices notification is not supported 594 */ 595 if (ret && ret != -EOPNOTSUPP) { 596 dev_err(&cldev->dev, "Could not reg notif event ret=%d\n", ret); 597 goto err_disable; 598 } 599 600 wd_info.firmware_version = mei_cldev_ver(cldev); 601 602 if (wdt->resp_required) 603 ret = mei_wdt_ping(wdt); 604 else 605 ret = mei_wdt_register(wdt); 606 607 if (ret) 608 goto err_disable; 609 610 dbgfs_register(wdt); 611 612 return 0; 613 614err_disable: 615 mei_cldev_disable(cldev); 616 617err_out: 618 kfree(wdt); 619 620 return ret; 621} 622 623static void mei_wdt_remove(struct mei_cl_device *cldev) 624{ 625 struct mei_wdt *wdt = mei_cldev_get_drvdata(cldev); 626 627 /* Free the caller in case of fw initiated or unexpected reset */ 628 if (!completion_done(&wdt->response)) 629 complete(&wdt->response); 630 631 cancel_work_sync(&wdt->unregister); 632 633 mei_wdt_unregister(wdt); 634 635 mei_cldev_disable(cldev); 636 637 dbgfs_unregister(wdt); 638 639 kfree(wdt); 640} 641 642#define MEI_UUID_WD UUID_LE(0x05B79A6F, 0x4628, 0x4D7F, \ 643 0x89, 0x9D, 0xA9, 0x15, 0x14, 0xCB, 0x32, 0xAB) 644 645static const struct mei_cl_device_id mei_wdt_tbl[] = { 646 { .uuid = MEI_UUID_WD, .version = MEI_CL_VERSION_ANY }, 647 /* required last entry */ 648 { } 649}; 650MODULE_DEVICE_TABLE(mei, mei_wdt_tbl); 651 652static struct mei_cl_driver mei_wdt_driver = { 653 .id_table = mei_wdt_tbl, 654 .name = KBUILD_MODNAME, 655 656 .probe = mei_wdt_probe, 657 .remove = mei_wdt_remove, 658}; 659 660module_mei_cl_driver(mei_wdt_driver); 661 662MODULE_AUTHOR("Intel Corporation"); 663MODULE_LICENSE("GPL v2"); 664MODULE_DESCRIPTION("Device driver for Intel MEI iAMT watchdog");