linux/drivers/watchdog/mei_wdt.c
<<
>>
Prefs
   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");
 665