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
 386        ret = watchdog_register_device(&wdt->wdd);
 387        if (ret)
 388                watchdog_set_drvdata(&wdt->wdd, NULL);
 389
 390        wdt->state = MEI_WDT_IDLE;
 391
 392out:
 393        mutex_unlock(&wdt->reg_lock);
 394        return ret;
 395}
 396
 397static void mei_wdt_unregister_work(struct work_struct *work)
 398{
 399        struct mei_wdt *wdt = container_of(work, struct mei_wdt, unregister);
 400
 401        mei_wdt_unregister(wdt);
 402}
 403
 404/**
 405 * mei_wdt_rx - callback for data receive
 406 *
 407 * @cldev: bus device
 408 */
 409static void mei_wdt_rx(struct mei_cl_device *cldev)
 410{
 411        struct mei_wdt *wdt = mei_cldev_get_drvdata(cldev);
 412        struct mei_wdt_start_response res;
 413        const size_t res_len = sizeof(res);
 414        int ret;
 415
 416        ret = mei_cldev_recv(wdt->cldev, (u8 *)&res, res_len);
 417        if (ret < 0) {
 418                dev_err(&cldev->dev, "failure in recv %d\n", ret);
 419                return;
 420        }
 421
 422        /* Empty response can be sent on stop */
 423        if (ret == 0)
 424                return;
 425
 426        if (ret < sizeof(struct mei_mc_hdr)) {
 427                dev_err(&cldev->dev, "recv small data %d\n", ret);
 428                return;
 429        }
 430
 431        if (res.hdr.command != MEI_MANAGEMENT_CONTROL ||
 432            res.hdr.versionnumber != MEI_MC_VERSION_NUMBER) {
 433                dev_err(&cldev->dev, "wrong command received\n");
 434                return;
 435        }
 436
 437        if (res.hdr.subcommand != MEI_MC_START_WD_TIMER_RES) {
 438                dev_warn(&cldev->dev, "unsupported command %d :%s[%d]\n",
 439                         res.hdr.subcommand,
 440                         mei_wdt_state_str(wdt->state),
 441                         wdt->state);
 442                return;
 443        }
 444
 445        /* Run the unregistration in a worker as this can be
 446         * run only after ping completion, otherwise the flow will
 447         * deadlock on watchdog core mutex.
 448         */
 449        if (wdt->state == MEI_WDT_RUNNING) {
 450                if (res.wdstate & MEI_WDT_WDSTATE_NOT_REQUIRED) {
 451                        wdt->state = MEI_WDT_NOT_REQUIRED;
 452                        schedule_work(&wdt->unregister);
 453                }
 454                goto out;
 455        }
 456
 457        if (wdt->state == MEI_WDT_PROBE) {
 458                if (res.wdstate & MEI_WDT_WDSTATE_NOT_REQUIRED) {
 459                        wdt->state = MEI_WDT_NOT_REQUIRED;
 460                } else {
 461                        /* stop the watchdog and register watchdog device */
 462                        mei_wdt_stop(wdt);
 463                        mei_wdt_register(wdt);
 464                }
 465                return;
 466        }
 467
 468        dev_warn(&cldev->dev, "not in correct state %s[%d]\n",
 469                         mei_wdt_state_str(wdt->state), wdt->state);
 470
 471out:
 472        if (!completion_done(&wdt->response))
 473                complete(&wdt->response);
 474}
 475
 476/*
 477 * mei_wdt_notif - callback for event notification
 478 *
 479 * @cldev: bus device
 480 */
 481static void mei_wdt_notif(struct mei_cl_device *cldev)
 482{
 483        struct mei_wdt *wdt = mei_cldev_get_drvdata(cldev);
 484
 485        if (wdt->state != MEI_WDT_NOT_REQUIRED)
 486                return;
 487
 488        mei_wdt_register(wdt);
 489}
 490
 491#if IS_ENABLED(CONFIG_DEBUG_FS)
 492
 493static ssize_t mei_dbgfs_read_activation(struct file *file, char __user *ubuf,
 494                                        size_t cnt, loff_t *ppos)
 495{
 496        struct mei_wdt *wdt = file->private_data;
 497        const size_t bufsz = 32;
 498        char buf[32];
 499        ssize_t pos;
 500
 501        mutex_lock(&wdt->reg_lock);
 502        pos = scnprintf(buf, bufsz, "%s\n",
 503                __mei_wdt_is_registered(wdt) ? "activated" : "deactivated");
 504        mutex_unlock(&wdt->reg_lock);
 505
 506        return simple_read_from_buffer(ubuf, cnt, ppos, buf, pos);
 507}
 508
 509static const struct file_operations dbgfs_fops_activation = {
 510        .open    = simple_open,
 511        .read    = mei_dbgfs_read_activation,
 512        .llseek  = generic_file_llseek,
 513};
 514
 515static ssize_t mei_dbgfs_read_state(struct file *file, char __user *ubuf,
 516                                    size_t cnt, loff_t *ppos)
 517{
 518        struct mei_wdt *wdt = file->private_data;
 519        char buf[32];
 520        ssize_t pos;
 521
 522        pos = scnprintf(buf, sizeof(buf), "state: %s\n",
 523                        mei_wdt_state_str(wdt->state));
 524
 525        return simple_read_from_buffer(ubuf, cnt, ppos, buf, pos);
 526}
 527
 528static const struct file_operations dbgfs_fops_state = {
 529        .open = simple_open,
 530        .read = mei_dbgfs_read_state,
 531        .llseek = generic_file_llseek,
 532};
 533
 534static void dbgfs_unregister(struct mei_wdt *wdt)
 535{
 536        debugfs_remove_recursive(wdt->dbgfs_dir);
 537        wdt->dbgfs_dir = NULL;
 538}
 539
 540static void dbgfs_register(struct mei_wdt *wdt)
 541{
 542        struct dentry *dir;
 543
 544        dir = debugfs_create_dir(KBUILD_MODNAME, NULL);
 545        wdt->dbgfs_dir = dir;
 546
 547        debugfs_create_file("state", S_IRUSR, dir, wdt, &dbgfs_fops_state);
 548
 549        debugfs_create_file("activation", S_IRUSR, dir, wdt,
 550                            &dbgfs_fops_activation);
 551}
 552
 553#else
 554
 555static inline void dbgfs_unregister(struct mei_wdt *wdt) {}
 556static inline void dbgfs_register(struct mei_wdt *wdt) {}
 557#endif /* CONFIG_DEBUG_FS */
 558
 559static int mei_wdt_probe(struct mei_cl_device *cldev,
 560                         const struct mei_cl_device_id *id)
 561{
 562        struct mei_wdt *wdt;
 563        int ret;
 564
 565        wdt = kzalloc(sizeof(struct mei_wdt), GFP_KERNEL);
 566        if (!wdt)
 567                return -ENOMEM;
 568
 569        wdt->timeout = MEI_WDT_DEFAULT_TIMEOUT;
 570        wdt->state = MEI_WDT_PROBE;
 571        wdt->cldev = cldev;
 572        wdt->resp_required = mei_cldev_ver(cldev) > 0x1;
 573        mutex_init(&wdt->reg_lock);
 574        init_completion(&wdt->response);
 575        INIT_WORK(&wdt->unregister, mei_wdt_unregister_work);
 576
 577        mei_cldev_set_drvdata(cldev, wdt);
 578
 579        ret = mei_cldev_enable(cldev);
 580        if (ret < 0) {
 581                dev_err(&cldev->dev, "Could not enable cl device\n");
 582                goto err_out;
 583        }
 584
 585        ret = mei_cldev_register_rx_cb(wdt->cldev, mei_wdt_rx);
 586        if (ret) {
 587                dev_err(&cldev->dev, "Could not reg rx event ret=%d\n", ret);
 588                goto err_disable;
 589        }
 590
 591        ret = mei_cldev_register_notif_cb(wdt->cldev, mei_wdt_notif);
 592        /* on legacy devices notification is not supported
 593         */
 594        if (ret && ret != -EOPNOTSUPP) {
 595                dev_err(&cldev->dev, "Could not reg notif event ret=%d\n", ret);
 596                goto err_disable;
 597        }
 598
 599        wd_info.firmware_version = mei_cldev_ver(cldev);
 600
 601        if (wdt->resp_required)
 602                ret = mei_wdt_ping(wdt);
 603        else
 604                ret = mei_wdt_register(wdt);
 605
 606        if (ret)
 607                goto err_disable;
 608
 609        dbgfs_register(wdt);
 610
 611        return 0;
 612
 613err_disable:
 614        mei_cldev_disable(cldev);
 615
 616err_out:
 617        kfree(wdt);
 618
 619        return ret;
 620}
 621
 622static int mei_wdt_remove(struct mei_cl_device *cldev)
 623{
 624        struct mei_wdt *wdt = mei_cldev_get_drvdata(cldev);
 625
 626        /* Free the caller in case of fw initiated or unexpected reset */
 627        if (!completion_done(&wdt->response))
 628                complete(&wdt->response);
 629
 630        cancel_work_sync(&wdt->unregister);
 631
 632        mei_wdt_unregister(wdt);
 633
 634        mei_cldev_disable(cldev);
 635
 636        dbgfs_unregister(wdt);
 637
 638        kfree(wdt);
 639
 640        return 0;
 641}
 642
 643#define MEI_UUID_WD UUID_LE(0x05B79A6F, 0x4628, 0x4D7F, \
 644                            0x89, 0x9D, 0xA9, 0x15, 0x14, 0xCB, 0x32, 0xAB)
 645
 646static const struct mei_cl_device_id mei_wdt_tbl[] = {
 647        { .uuid = MEI_UUID_WD, .version = MEI_CL_VERSION_ANY },
 648        /* required last entry */
 649        { }
 650};
 651MODULE_DEVICE_TABLE(mei, mei_wdt_tbl);
 652
 653static struct mei_cl_driver mei_wdt_driver = {
 654        .id_table = mei_wdt_tbl,
 655        .name = KBUILD_MODNAME,
 656
 657        .probe = mei_wdt_probe,
 658        .remove = mei_wdt_remove,
 659};
 660
 661module_mei_cl_driver(mei_wdt_driver);
 662
 663MODULE_AUTHOR("Intel Corporation");
 664MODULE_LICENSE("GPL v2");
 665MODULE_DESCRIPTION("Device driver for Intel MEI iAMT watchdog");
 666