root/drivers/watchdog/mei_wdt.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mei_wdt_state_str
  2. mei_wdt_ping
  3. mei_wdt_stop
  4. mei_wdt_ops_start
  5. mei_wdt_ops_stop
  6. mei_wdt_ops_ping
  7. mei_wdt_ops_set_timeout
  8. __mei_wdt_is_registered
  9. mei_wdt_unregister
  10. mei_wdt_register
  11. mei_wdt_unregister_work
  12. mei_wdt_rx
  13. mei_wdt_notif
  14. mei_dbgfs_read_activation
  15. mei_dbgfs_read_state
  16. dbgfs_unregister
  17. dbgfs_register
  18. dbgfs_unregister
  19. dbgfs_register
  20. mei_wdt_probe
  21. mei_wdt_remove

   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  */
  49 enum 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 
  58 static 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  */
  92 struct 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  */
 116 struct 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  */
 130 struct 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  */
 143 struct 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  */
 154 struct 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  */
 166 static 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  */
 194 static 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  */
 220 static 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  */
 236 static 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  */
 262 static 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  */
 292 static 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 
 305 static 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 */
 314 static 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  */
 329 static 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  */
 339 static 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  */
 359 static 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 
 392 out:
 393         mutex_unlock(&wdt->reg_lock);
 394         return ret;
 395 }
 396 
 397 static 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  */
 409 static 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 
 471 out:
 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  */
 481 static 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 
 493 static 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 
 509 static const struct file_operations dbgfs_fops_activation = {
 510         .open    = simple_open,
 511         .read    = mei_dbgfs_read_activation,
 512         .llseek  = generic_file_llseek,
 513 };
 514 
 515 static 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 
 528 static const struct file_operations dbgfs_fops_state = {
 529         .open = simple_open,
 530         .read = mei_dbgfs_read_state,
 531         .llseek = generic_file_llseek,
 532 };
 533 
 534 static void dbgfs_unregister(struct mei_wdt *wdt)
 535 {
 536         debugfs_remove_recursive(wdt->dbgfs_dir);
 537         wdt->dbgfs_dir = NULL;
 538 }
 539 
 540 static 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 
 555 static inline void dbgfs_unregister(struct mei_wdt *wdt) {}
 556 static inline void dbgfs_register(struct mei_wdt *wdt) {}
 557 #endif /* CONFIG_DEBUG_FS */
 558 
 559 static 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 
 613 err_disable:
 614         mei_cldev_disable(cldev);
 615 
 616 err_out:
 617         kfree(wdt);
 618 
 619         return ret;
 620 }
 621 
 622 static 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 
 646 static 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 };
 651 MODULE_DEVICE_TABLE(mei, mei_wdt_tbl);
 652 
 653 static 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 
 661 module_mei_cl_driver(mei_wdt_driver);
 662 
 663 MODULE_AUTHOR("Intel Corporation");
 664 MODULE_LICENSE("GPL v2");
 665 MODULE_DESCRIPTION("Device driver for Intel MEI iAMT watchdog");

/* [<][>][^][v][top][bottom][index][help] */