1 /* 2 * watchdog_dev.c 3 * 4 * (c) Copyright 2008-2011 Alan Cox <alan@lxorguk.ukuu.org.uk>, 5 * All Rights Reserved. 6 * 7 * (c) Copyright 2008-2011 Wim Van Sebroeck <wim@iguana.be>. 8 * 9 * 10 * This source code is part of the generic code that can be used 11 * by all the watchdog timer drivers. 12 * 13 * This part of the generic code takes care of the following 14 * misc device: /dev/watchdog. 15 * 16 * Based on source code of the following authors: 17 * Matt Domsch <Matt_Domsch@dell.com>, 18 * Rob Radez <rob@osinvestor.com>, 19 * Rusty Lynch <rusty@linux.co.intel.com> 20 * Satyam Sharma <satyam@infradead.org> 21 * Randy Dunlap <randy.dunlap@oracle.com> 22 * 23 * This program is free software; you can redistribute it and/or 24 * modify it under the terms of the GNU General Public License 25 * as published by the Free Software Foundation; either version 26 * 2 of the License, or (at your option) any later version. 27 * 28 * Neither Alan Cox, CymruNet Ltd., Wim Van Sebroeck nor Iguana vzw. 29 * admit liability nor provide warranty for any of this software. 30 * This material is provided "AS-IS" and at no charge. 31 */ 32 33 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 34 35 #include <linux/cdev.h> /* For character device */ 36 #include <linux/errno.h> /* For the -ENODEV/... values */ 37 #include <linux/fs.h> /* For file operations */ 38 #include <linux/init.h> /* For __init/__exit/... */ 39 #include <linux/kernel.h> /* For printk/panic/... */ 40 #include <linux/kref.h> /* For data references */ 41 #include <linux/miscdevice.h> /* For handling misc devices */ 42 #include <linux/module.h> /* For module stuff/... */ 43 #include <linux/mutex.h> /* For mutexes */ 44 #include <linux/slab.h> /* For memory functions */ 45 #include <linux/types.h> /* For standard types (like size_t) */ 46 #include <linux/watchdog.h> /* For watchdog specific items */ 47 #include <linux/uaccess.h> /* For copy_to_user/put_user/... */ 48 49 #include "watchdog_core.h" 50 51 /* 52 * struct watchdog_core_data - watchdog core internal data 53 * @kref: Reference count. 54 * @cdev: The watchdog's Character device. 55 * @wdd: Pointer to watchdog device. 56 * @lock: Lock for watchdog core. 57 * @status: Watchdog core internal status bits. 58 */ 59 struct watchdog_core_data { 60 struct kref kref; 61 struct cdev cdev; 62 struct watchdog_device *wdd; 63 struct mutex lock; 64 unsigned long status; /* Internal status bits */ 65 #define _WDOG_DEV_OPEN 0 /* Opened ? */ 66 #define _WDOG_ALLOW_RELEASE 1 /* Did we receive the magic char ? */ 67 }; 68 69 /* the dev_t structure to store the dynamically allocated watchdog devices */ 70 static dev_t watchdog_devt; 71 /* Reference to watchdog device behind /dev/watchdog */ 72 static struct watchdog_core_data *old_wd_data; 73 74 /* 75 * watchdog_ping: ping the watchdog. 76 * @wdd: the watchdog device to ping 77 * 78 * The caller must hold wd_data->lock. 79 * 80 * If the watchdog has no own ping operation then it needs to be 81 * restarted via the start operation. This wrapper function does 82 * exactly that. 83 * We only ping when the watchdog device is running. 84 */ 85 86 static int watchdog_ping(struct watchdog_device *wdd) 87 { 88 int err; 89 90 if (!watchdog_active(wdd)) 91 return 0; 92 93 if (wdd->ops->ping) 94 err = wdd->ops->ping(wdd); /* ping the watchdog */ 95 else 96 err = wdd->ops->start(wdd); /* restart watchdog */ 97 98 return err; 99 } 100 101 /* 102 * watchdog_start: wrapper to start the watchdog. 103 * @wdd: the watchdog device to start 104 * 105 * The caller must hold wd_data->lock. 106 * 107 * Start the watchdog if it is not active and mark it active. 108 * This function returns zero on success or a negative errno code for 109 * failure. 110 */ 111 112 static int watchdog_start(struct watchdog_device *wdd) 113 { 114 int err; 115 116 if (watchdog_active(wdd)) 117 return 0; 118 119 err = wdd->ops->start(wdd); 120 if (err == 0) 121 set_bit(WDOG_ACTIVE, &wdd->status); 122 123 return err; 124 } 125 126 /* 127 * watchdog_stop: wrapper to stop the watchdog. 128 * @wdd: the watchdog device to stop 129 * 130 * The caller must hold wd_data->lock. 131 * 132 * Stop the watchdog if it is still active and unmark it active. 133 * This function returns zero on success or a negative errno code for 134 * failure. 135 * If the 'nowayout' feature was set, the watchdog cannot be stopped. 136 */ 137 138 static int watchdog_stop(struct watchdog_device *wdd) 139 { 140 int err; 141 142 if (!watchdog_active(wdd)) 143 return 0; 144 145 if (test_bit(WDOG_NO_WAY_OUT, &wdd->status)) { 146 dev_info(wdd->dev, "nowayout prevents watchdog being stopped!\n"); 147 return -EBUSY; 148 } 149 150 err = wdd->ops->stop(wdd); 151 if (err == 0) 152 clear_bit(WDOG_ACTIVE, &wdd->status); 153 154 return err; 155 } 156 157 /* 158 * watchdog_get_status: wrapper to get the watchdog status 159 * @wdd: the watchdog device to get the status from 160 * 161 * The caller must hold wd_data->lock. 162 * 163 * Get the watchdog's status flags. 164 */ 165 166 static unsigned int watchdog_get_status(struct watchdog_device *wdd) 167 { 168 if (!wdd->ops->status) 169 return 0; 170 171 return wdd->ops->status(wdd); 172 } 173 174 /* 175 * watchdog_set_timeout: set the watchdog timer timeout 176 * @wdd: the watchdog device to set the timeout for 177 * @timeout: timeout to set in seconds 178 * 179 * The caller must hold wd_data->lock. 180 */ 181 182 static int watchdog_set_timeout(struct watchdog_device *wdd, 183 unsigned int timeout) 184 { 185 if (!wdd->ops->set_timeout || !(wdd->info->options & WDIOF_SETTIMEOUT)) 186 return -EOPNOTSUPP; 187 188 if (watchdog_timeout_invalid(wdd, timeout)) 189 return -EINVAL; 190 191 return wdd->ops->set_timeout(wdd, timeout); 192 } 193 194 /* 195 * watchdog_get_timeleft: wrapper to get the time left before a reboot 196 * @wdd: the watchdog device to get the remaining time from 197 * @timeleft: the time that's left 198 * 199 * The caller must hold wd_data->lock. 200 * 201 * Get the time before a watchdog will reboot (if not pinged). 202 */ 203 204 static int watchdog_get_timeleft(struct watchdog_device *wdd, 205 unsigned int *timeleft) 206 { 207 *timeleft = 0; 208 209 if (!wdd->ops->get_timeleft) 210 return -EOPNOTSUPP; 211 212 *timeleft = wdd->ops->get_timeleft(wdd); 213 214 return 0; 215 } 216 217 #ifdef CONFIG_WATCHDOG_SYSFS 218 static ssize_t nowayout_show(struct device *dev, struct device_attribute *attr, 219 char *buf) 220 { 221 struct watchdog_device *wdd = dev_get_drvdata(dev); 222 223 return sprintf(buf, "%d\n", !!test_bit(WDOG_NO_WAY_OUT, &wdd->status)); 224 } 225 static DEVICE_ATTR_RO(nowayout); 226 227 static ssize_t status_show(struct device *dev, struct device_attribute *attr, 228 char *buf) 229 { 230 struct watchdog_device *wdd = dev_get_drvdata(dev); 231 struct watchdog_core_data *wd_data = wdd->wd_data; 232 unsigned int status; 233 234 mutex_lock(&wd_data->lock); 235 status = watchdog_get_status(wdd); 236 mutex_unlock(&wd_data->lock); 237 238 return sprintf(buf, "%u\n", status); 239 } 240 static DEVICE_ATTR_RO(status); 241 242 static ssize_t bootstatus_show(struct device *dev, 243 struct device_attribute *attr, char *buf) 244 { 245 struct watchdog_device *wdd = dev_get_drvdata(dev); 246 247 return sprintf(buf, "%u\n", wdd->bootstatus); 248 } 249 static DEVICE_ATTR_RO(bootstatus); 250 251 static ssize_t timeleft_show(struct device *dev, struct device_attribute *attr, 252 char *buf) 253 { 254 struct watchdog_device *wdd = dev_get_drvdata(dev); 255 struct watchdog_core_data *wd_data = wdd->wd_data; 256 ssize_t status; 257 unsigned int val; 258 259 mutex_lock(&wd_data->lock); 260 status = watchdog_get_timeleft(wdd, &val); 261 mutex_unlock(&wd_data->lock); 262 if (!status) 263 status = sprintf(buf, "%u\n", val); 264 265 return status; 266 } 267 static DEVICE_ATTR_RO(timeleft); 268 269 static ssize_t timeout_show(struct device *dev, struct device_attribute *attr, 270 char *buf) 271 { 272 struct watchdog_device *wdd = dev_get_drvdata(dev); 273 274 return sprintf(buf, "%u\n", wdd->timeout); 275 } 276 static DEVICE_ATTR_RO(timeout); 277 278 static ssize_t identity_show(struct device *dev, struct device_attribute *attr, 279 char *buf) 280 { 281 struct watchdog_device *wdd = dev_get_drvdata(dev); 282 283 return sprintf(buf, "%s\n", wdd->info->identity); 284 } 285 static DEVICE_ATTR_RO(identity); 286 287 static ssize_t state_show(struct device *dev, struct device_attribute *attr, 288 char *buf) 289 { 290 struct watchdog_device *wdd = dev_get_drvdata(dev); 291 292 if (watchdog_active(wdd)) 293 return sprintf(buf, "active\n"); 294 295 return sprintf(buf, "inactive\n"); 296 } 297 static DEVICE_ATTR_RO(state); 298 299 static umode_t wdt_is_visible(struct kobject *kobj, struct attribute *attr, 300 int n) 301 { 302 struct device *dev = container_of(kobj, struct device, kobj); 303 struct watchdog_device *wdd = dev_get_drvdata(dev); 304 umode_t mode = attr->mode; 305 306 if (attr == &dev_attr_status.attr && !wdd->ops->status) 307 mode = 0; 308 else if (attr == &dev_attr_timeleft.attr && !wdd->ops->get_timeleft) 309 mode = 0; 310 311 return mode; 312 } 313 static struct attribute *wdt_attrs[] = { 314 &dev_attr_state.attr, 315 &dev_attr_identity.attr, 316 &dev_attr_timeout.attr, 317 &dev_attr_timeleft.attr, 318 &dev_attr_bootstatus.attr, 319 &dev_attr_status.attr, 320 &dev_attr_nowayout.attr, 321 NULL, 322 }; 323 324 static const struct attribute_group wdt_group = { 325 .attrs = wdt_attrs, 326 .is_visible = wdt_is_visible, 327 }; 328 __ATTRIBUTE_GROUPS(wdt); 329 #else 330 #define wdt_groups NULL 331 #endif 332 333 /* 334 * watchdog_ioctl_op: call the watchdog drivers ioctl op if defined 335 * @wdd: the watchdog device to do the ioctl on 336 * @cmd: watchdog command 337 * @arg: argument pointer 338 * 339 * The caller must hold wd_data->lock. 340 */ 341 342 static int watchdog_ioctl_op(struct watchdog_device *wdd, unsigned int cmd, 343 unsigned long arg) 344 { 345 if (!wdd->ops->ioctl) 346 return -ENOIOCTLCMD; 347 348 return wdd->ops->ioctl(wdd, cmd, arg); 349 } 350 351 /* 352 * watchdog_write: writes to the watchdog. 353 * @file: file from VFS 354 * @data: user address of data 355 * @len: length of data 356 * @ppos: pointer to the file offset 357 * 358 * A write to a watchdog device is defined as a keepalive ping. 359 * Writing the magic 'V' sequence allows the next close to turn 360 * off the watchdog (if 'nowayout' is not set). 361 */ 362 363 static ssize_t watchdog_write(struct file *file, const char __user *data, 364 size_t len, loff_t *ppos) 365 { 366 struct watchdog_core_data *wd_data = file->private_data; 367 struct watchdog_device *wdd; 368 int err; 369 size_t i; 370 char c; 371 372 if (len == 0) 373 return 0; 374 375 /* 376 * Note: just in case someone wrote the magic character 377 * five months ago... 378 */ 379 clear_bit(_WDOG_ALLOW_RELEASE, &wd_data->status); 380 381 /* scan to see whether or not we got the magic character */ 382 for (i = 0; i != len; i++) { 383 if (get_user(c, data + i)) 384 return -EFAULT; 385 if (c == 'V') 386 set_bit(_WDOG_ALLOW_RELEASE, &wd_data->status); 387 } 388 389 /* someone wrote to us, so we send the watchdog a keepalive ping */ 390 391 err = -ENODEV; 392 mutex_lock(&wd_data->lock); 393 wdd = wd_data->wdd; 394 if (wdd) 395 err = watchdog_ping(wdd); 396 mutex_unlock(&wd_data->lock); 397 398 if (err < 0) 399 return err; 400 401 return len; 402 } 403 404 /* 405 * watchdog_ioctl: handle the different ioctl's for the watchdog device. 406 * @file: file handle to the device 407 * @cmd: watchdog command 408 * @arg: argument pointer 409 * 410 * The watchdog API defines a common set of functions for all watchdogs 411 * according to their available features. 412 */ 413 414 static long watchdog_ioctl(struct file *file, unsigned int cmd, 415 unsigned long arg) 416 { 417 struct watchdog_core_data *wd_data = file->private_data; 418 void __user *argp = (void __user *)arg; 419 struct watchdog_device *wdd; 420 int __user *p = argp; 421 unsigned int val; 422 int err; 423 424 mutex_lock(&wd_data->lock); 425 426 wdd = wd_data->wdd; 427 if (!wdd) { 428 err = -ENODEV; 429 goto out_ioctl; 430 } 431 432 err = watchdog_ioctl_op(wdd, cmd, arg); 433 if (err != -ENOIOCTLCMD) 434 goto out_ioctl; 435 436 switch (cmd) { 437 case WDIOC_GETSUPPORT: 438 err = copy_to_user(argp, wdd->info, 439 sizeof(struct watchdog_info)) ? -EFAULT : 0; 440 break; 441 case WDIOC_GETSTATUS: 442 val = watchdog_get_status(wdd); 443 err = put_user(val, p); 444 break; 445 case WDIOC_GETBOOTSTATUS: 446 err = put_user(wdd->bootstatus, p); 447 break; 448 case WDIOC_SETOPTIONS: 449 if (get_user(val, p)) { 450 err = -EFAULT; 451 break; 452 } 453 if (val & WDIOS_DISABLECARD) { 454 err = watchdog_stop(wdd); 455 if (err < 0) 456 break; 457 } 458 if (val & WDIOS_ENABLECARD) 459 err = watchdog_start(wdd); 460 break; 461 case WDIOC_KEEPALIVE: 462 if (!(wdd->info->options & WDIOF_KEEPALIVEPING)) { 463 err = -EOPNOTSUPP; 464 break; 465 } 466 err = watchdog_ping(wdd); 467 break; 468 case WDIOC_SETTIMEOUT: 469 if (get_user(val, p)) { 470 err = -EFAULT; 471 break; 472 } 473 err = watchdog_set_timeout(wdd, val); 474 if (err < 0) 475 break; 476 /* If the watchdog is active then we send a keepalive ping 477 * to make sure that the watchdog keep's running (and if 478 * possible that it takes the new timeout) */ 479 err = watchdog_ping(wdd); 480 if (err < 0) 481 break; 482 /* Fall */ 483 case WDIOC_GETTIMEOUT: 484 /* timeout == 0 means that we don't know the timeout */ 485 if (wdd->timeout == 0) { 486 err = -EOPNOTSUPP; 487 break; 488 } 489 err = put_user(wdd->timeout, p); 490 break; 491 case WDIOC_GETTIMELEFT: 492 err = watchdog_get_timeleft(wdd, &val); 493 if (err < 0) 494 break; 495 err = put_user(val, p); 496 break; 497 default: 498 err = -ENOTTY; 499 break; 500 } 501 502 out_ioctl: 503 mutex_unlock(&wd_data->lock); 504 return err; 505 } 506 507 /* 508 * watchdog_open: open the /dev/watchdog* devices. 509 * @inode: inode of device 510 * @file: file handle to device 511 * 512 * When the /dev/watchdog* device gets opened, we start the watchdog. 513 * Watch out: the /dev/watchdog device is single open, so we make sure 514 * it can only be opened once. 515 */ 516 517 static int watchdog_open(struct inode *inode, struct file *file) 518 { 519 struct watchdog_core_data *wd_data; 520 struct watchdog_device *wdd; 521 int err; 522 523 /* Get the corresponding watchdog device */ 524 if (imajor(inode) == MISC_MAJOR) 525 wd_data = old_wd_data; 526 else 527 wd_data = container_of(inode->i_cdev, struct watchdog_core_data, 528 cdev); 529 530 /* the watchdog is single open! */ 531 if (test_and_set_bit(_WDOG_DEV_OPEN, &wd_data->status)) 532 return -EBUSY; 533 534 wdd = wd_data->wdd; 535 536 /* 537 * If the /dev/watchdog device is open, we don't want the module 538 * to be unloaded. 539 */ 540 if (!try_module_get(wdd->ops->owner)) { 541 err = -EBUSY; 542 goto out_clear; 543 } 544 545 err = watchdog_start(wdd); 546 if (err < 0) 547 goto out_mod; 548 549 file->private_data = wd_data; 550 551 kref_get(&wd_data->kref); 552 553 /* dev/watchdog is a virtual (and thus non-seekable) filesystem */ 554 return nonseekable_open(inode, file); 555 556 out_mod: 557 module_put(wd_data->wdd->ops->owner); 558 out_clear: 559 clear_bit(_WDOG_DEV_OPEN, &wd_data->status); 560 return err; 561 } 562 563 static void watchdog_core_data_release(struct kref *kref) 564 { 565 struct watchdog_core_data *wd_data; 566 567 wd_data = container_of(kref, struct watchdog_core_data, kref); 568 569 kfree(wd_data); 570 } 571 572 /* 573 * watchdog_release: release the watchdog device. 574 * @inode: inode of device 575 * @file: file handle to device 576 * 577 * This is the code for when /dev/watchdog gets closed. We will only 578 * stop the watchdog when we have received the magic char (and nowayout 579 * was not set), else the watchdog will keep running. 580 */ 581 582 static int watchdog_release(struct inode *inode, struct file *file) 583 { 584 struct watchdog_core_data *wd_data = file->private_data; 585 struct watchdog_device *wdd; 586 int err = -EBUSY; 587 588 mutex_lock(&wd_data->lock); 589 590 wdd = wd_data->wdd; 591 if (!wdd) 592 goto done; 593 594 /* 595 * We only stop the watchdog if we received the magic character 596 * or if WDIOF_MAGICCLOSE is not set. If nowayout was set then 597 * watchdog_stop will fail. 598 */ 599 if (!test_bit(WDOG_ACTIVE, &wdd->status)) 600 err = 0; 601 else if (test_and_clear_bit(_WDOG_ALLOW_RELEASE, &wd_data->status) || 602 !(wdd->info->options & WDIOF_MAGICCLOSE)) 603 err = watchdog_stop(wdd); 604 605 /* If the watchdog was not stopped, send a keepalive ping */ 606 if (err < 0) { 607 dev_crit(wdd->dev, "watchdog did not stop!\n"); 608 watchdog_ping(wdd); 609 } 610 611 /* make sure that /dev/watchdog can be re-opened */ 612 clear_bit(_WDOG_DEV_OPEN, &wd_data->status); 613 614 done: 615 mutex_unlock(&wd_data->lock); 616 /* Allow the owner module to be unloaded again */ 617 module_put(wd_data->cdev.owner); 618 kref_put(&wd_data->kref, watchdog_core_data_release); 619 return 0; 620 } 621 622 static const struct file_operations watchdog_fops = { 623 .owner = THIS_MODULE, 624 .write = watchdog_write, 625 .unlocked_ioctl = watchdog_ioctl, 626 .open = watchdog_open, 627 .release = watchdog_release, 628 }; 629 630 static struct miscdevice watchdog_miscdev = { 631 .minor = WATCHDOG_MINOR, 632 .name = "watchdog", 633 .fops = &watchdog_fops, 634 }; 635 636 /* 637 * watchdog_cdev_register: register watchdog character device 638 * @wdd: watchdog device 639 * @devno: character device number 640 * 641 * Register a watchdog character device including handling the legacy 642 * /dev/watchdog node. /dev/watchdog is actually a miscdevice and 643 * thus we set it up like that. 644 */ 645 646 static int watchdog_cdev_register(struct watchdog_device *wdd, dev_t devno) 647 { 648 struct watchdog_core_data *wd_data; 649 int err; 650 651 wd_data = kzalloc(sizeof(struct watchdog_core_data), GFP_KERNEL); 652 if (!wd_data) 653 return -ENOMEM; 654 kref_init(&wd_data->kref); 655 mutex_init(&wd_data->lock); 656 657 wd_data->wdd = wdd; 658 wdd->wd_data = wd_data; 659 660 if (wdd->id == 0) { 661 old_wd_data = wd_data; 662 watchdog_miscdev.parent = wdd->parent; 663 err = misc_register(&watchdog_miscdev); 664 if (err != 0) { 665 pr_err("%s: cannot register miscdev on minor=%d (err=%d).\n", 666 wdd->info->identity, WATCHDOG_MINOR, err); 667 if (err == -EBUSY) 668 pr_err("%s: a legacy watchdog module is probably present.\n", 669 wdd->info->identity); 670 old_wd_data = NULL; 671 kfree(wd_data); 672 return err; 673 } 674 } 675 676 /* Fill in the data structures */ 677 cdev_init(&wd_data->cdev, &watchdog_fops); 678 wd_data->cdev.owner = wdd->ops->owner; 679 680 /* Add the device */ 681 err = cdev_add(&wd_data->cdev, devno, 1); 682 if (err) { 683 pr_err("watchdog%d unable to add device %d:%d\n", 684 wdd->id, MAJOR(watchdog_devt), wdd->id); 685 if (wdd->id == 0) { 686 misc_deregister(&watchdog_miscdev); 687 old_wd_data = NULL; 688 kref_put(&wd_data->kref, watchdog_core_data_release); 689 } 690 } 691 return err; 692 } 693 694 /* 695 * watchdog_cdev_unregister: unregister watchdog character device 696 * @watchdog: watchdog device 697 * 698 * Unregister watchdog character device and if needed the legacy 699 * /dev/watchdog device. 700 */ 701 702 static void watchdog_cdev_unregister(struct watchdog_device *wdd) 703 { 704 struct watchdog_core_data *wd_data = wdd->wd_data; 705 706 cdev_del(&wd_data->cdev); 707 if (wdd->id == 0) { 708 misc_deregister(&watchdog_miscdev); 709 old_wd_data = NULL; 710 } 711 712 mutex_lock(&wd_data->lock); 713 wd_data->wdd = NULL; 714 wdd->wd_data = NULL; 715 mutex_unlock(&wd_data->lock); 716 717 kref_put(&wd_data->kref, watchdog_core_data_release); 718 } 719 720 static struct class watchdog_class = { 721 .name = "watchdog", 722 .owner = THIS_MODULE, 723 .dev_groups = wdt_groups, 724 }; 725 726 /* 727 * watchdog_dev_register: register a watchdog device 728 * @wdd: watchdog device 729 * 730 * Register a watchdog device including handling the legacy 731 * /dev/watchdog node. /dev/watchdog is actually a miscdevice and 732 * thus we set it up like that. 733 */ 734 735 int watchdog_dev_register(struct watchdog_device *wdd) 736 { 737 struct device *dev; 738 dev_t devno; 739 int ret; 740 741 devno = MKDEV(MAJOR(watchdog_devt), wdd->id); 742 743 ret = watchdog_cdev_register(wdd, devno); 744 if (ret) 745 return ret; 746 747 dev = device_create(&watchdog_class, wdd->parent, devno, wdd, 748 "watchdog%d", wdd->id); 749 if (IS_ERR(dev)) { 750 watchdog_cdev_unregister(wdd); 751 return PTR_ERR(dev); 752 } 753 wdd->dev = dev; 754 755 return ret; 756 } 757 758 /* 759 * watchdog_dev_unregister: unregister a watchdog device 760 * @watchdog: watchdog device 761 * 762 * Unregister watchdog device and if needed the legacy 763 * /dev/watchdog device. 764 */ 765 766 void watchdog_dev_unregister(struct watchdog_device *wdd) 767 { 768 device_destroy(&watchdog_class, wdd->dev->devt); 769 wdd->dev = NULL; 770 watchdog_cdev_unregister(wdd); 771 } 772 773 /* 774 * watchdog_dev_init: init dev part of watchdog core 775 * 776 * Allocate a range of chardev nodes to use for watchdog devices 777 */ 778 779 int __init watchdog_dev_init(void) 780 { 781 int err; 782 783 err = class_register(&watchdog_class); 784 if (err < 0) { 785 pr_err("couldn't register class\n"); 786 return err; 787 } 788 789 err = alloc_chrdev_region(&watchdog_devt, 0, MAX_DOGS, "watchdog"); 790 if (err < 0) { 791 pr_err("watchdog: unable to allocate char dev region\n"); 792 class_unregister(&watchdog_class); 793 return err; 794 } 795 796 return 0; 797 } 798 799 /* 800 * watchdog_dev_exit: exit dev part of watchdog core 801 * 802 * Release the range of chardev nodes used for watchdog devices 803 */ 804 805 void __exit watchdog_dev_exit(void) 806 { 807 unregister_chrdev_region(watchdog_devt, MAX_DOGS); 808 class_unregister(&watchdog_class); 809 } 810