linux/drivers/watchdog/wdt_pci.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 *      Industrial Computer Source PCI-WDT500/501 driver
   4 *
   5 *      (c) Copyright 1996-1997 Alan Cox <alan@lxorguk.ukuu.org.uk>,
   6 *                                              All Rights Reserved.
   7 *
   8 *      Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
   9 *      warranty for any of this software. This material is provided
  10 *      "AS-IS" and at no charge.
  11 *
  12 *      (c) Copyright 1995    Alan Cox <alan@lxorguk.ukuu.org.uk>
  13 *
  14 *      Release 0.10.
  15 *
  16 *      Fixes
  17 *              Dave Gregorich  :       Modularisation and minor bugs
  18 *              Alan Cox        :       Added the watchdog ioctl() stuff
  19 *              Alan Cox        :       Fixed the reboot problem (as noted by
  20 *                                      Matt Crocker).
  21 *              Alan Cox        :       Added wdt= boot option
  22 *              Alan Cox        :       Cleaned up copy/user stuff
  23 *              Tim Hockin      :       Added insmod parameters, comment cleanup
  24 *                                      Parameterized timeout
  25 *              JP Nollmann     :       Added support for PCI wdt501p
  26 *              Alan Cox        :       Split ISA and PCI cards into two drivers
  27 *              Jeff Garzik     :       PCI cleanups
  28 *              Tigran Aivazian :       Restructured wdtpci_init_one() to handle
  29 *                                      failures
  30 *              Joel Becker     :       Added WDIOC_GET/SETTIMEOUT
  31 *              Zwane Mwaikambo :       Magic char closing, locking changes,
  32 *                                      cleanups
  33 *              Matt Domsch     :       nowayout module option
  34 */
  35
  36#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  37
  38#include <linux/interrupt.h>
  39#include <linux/module.h>
  40#include <linux/moduleparam.h>
  41#include <linux/types.h>
  42#include <linux/miscdevice.h>
  43#include <linux/watchdog.h>
  44#include <linux/ioport.h>
  45#include <linux/delay.h>
  46#include <linux/notifier.h>
  47#include <linux/reboot.h>
  48#include <linux/fs.h>
  49#include <linux/pci.h>
  50#include <linux/io.h>
  51#include <linux/uaccess.h>
  52
  53
  54#define WDT_IS_PCI
  55#include "wd501p.h"
  56
  57/* We can only use 1 card due to the /dev/watchdog restriction */
  58static int dev_count;
  59
  60static unsigned long open_lock;
  61static DEFINE_SPINLOCK(wdtpci_lock);
  62static char expect_close;
  63
  64static resource_size_t io;
  65static int irq;
  66
  67/* Default timeout */
  68#define WD_TIMO 60                      /* Default heartbeat = 60 seconds */
  69
  70static int heartbeat = WD_TIMO;
  71static int wd_heartbeat;
  72module_param(heartbeat, int, 0);
  73MODULE_PARM_DESC(heartbeat,
  74                "Watchdog heartbeat in seconds. (0<heartbeat<65536, default="
  75                                __MODULE_STRING(WD_TIMO) ")");
  76
  77static bool nowayout = WATCHDOG_NOWAYOUT;
  78module_param(nowayout, bool, 0);
  79MODULE_PARM_DESC(nowayout,
  80                "Watchdog cannot be stopped once started (default="
  81                                __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
  82
  83/* Support for the Fan Tachometer on the PCI-WDT501 */
  84static int tachometer;
  85module_param(tachometer, int, 0);
  86MODULE_PARM_DESC(tachometer,
  87                "PCI-WDT501 Fan Tachometer support (0=disable, default=0)");
  88
  89static int type = 500;
  90module_param(type, int, 0);
  91MODULE_PARM_DESC(type,
  92                "PCI-WDT501 Card type (500 or 501 , default=500)");
  93
  94/*
  95 *      Programming support
  96 */
  97
  98static void wdtpci_ctr_mode(int ctr, int mode)
  99{
 100        ctr <<= 6;
 101        ctr |= 0x30;
 102        ctr |= (mode << 1);
 103        outb(ctr, WDT_CR);
 104        udelay(8);
 105}
 106
 107static void wdtpci_ctr_load(int ctr, int val)
 108{
 109        outb(val & 0xFF, WDT_COUNT0 + ctr);
 110        udelay(8);
 111        outb(val >> 8, WDT_COUNT0 + ctr);
 112        udelay(8);
 113}
 114
 115/**
 116 *      wdtpci_start:
 117 *
 118 *      Start the watchdog driver.
 119 */
 120
 121static int wdtpci_start(void)
 122{
 123        unsigned long flags;
 124
 125        spin_lock_irqsave(&wdtpci_lock, flags);
 126
 127        /*
 128         * "pet" the watchdog, as Access says.
 129         * This resets the clock outputs.
 130         */
 131        inb(WDT_DC);                    /* Disable watchdog */
 132        udelay(8);
 133        wdtpci_ctr_mode(2, 0);          /* Program CTR2 for Mode 0:
 134                                                Pulse on Terminal Count */
 135        outb(0, WDT_DC);                /* Enable watchdog */
 136        udelay(8);
 137        inb(WDT_DC);                    /* Disable watchdog */
 138        udelay(8);
 139        outb(0, WDT_CLOCK);             /* 2.0833MHz clock */
 140        udelay(8);
 141        inb(WDT_BUZZER);                /* disable */
 142        udelay(8);
 143        inb(WDT_OPTONOTRST);            /* disable */
 144        udelay(8);
 145        inb(WDT_OPTORST);               /* disable */
 146        udelay(8);
 147        inb(WDT_PROGOUT);               /* disable */
 148        udelay(8);
 149        wdtpci_ctr_mode(0, 3);          /* Program CTR0 for Mode 3:
 150                                                Square Wave Generator */
 151        wdtpci_ctr_mode(1, 2);          /* Program CTR1 for Mode 2:
 152                                                Rate Generator */
 153        wdtpci_ctr_mode(2, 1);          /* Program CTR2 for Mode 1:
 154                                                Retriggerable One-Shot */
 155        wdtpci_ctr_load(0, 20833);      /* count at 100Hz */
 156        wdtpci_ctr_load(1, wd_heartbeat);/* Heartbeat */
 157        /* DO NOT LOAD CTR2 on PCI card! -- JPN */
 158        outb(0, WDT_DC);                /* Enable watchdog */
 159        udelay(8);
 160
 161        spin_unlock_irqrestore(&wdtpci_lock, flags);
 162        return 0;
 163}
 164
 165/**
 166 *      wdtpci_stop:
 167 *
 168 *      Stop the watchdog driver.
 169 */
 170
 171static int wdtpci_stop(void)
 172{
 173        unsigned long flags;
 174
 175        /* Turn the card off */
 176        spin_lock_irqsave(&wdtpci_lock, flags);
 177        inb(WDT_DC);                    /* Disable watchdog */
 178        udelay(8);
 179        wdtpci_ctr_load(2, 0);          /* 0 length reset pulses now */
 180        spin_unlock_irqrestore(&wdtpci_lock, flags);
 181        return 0;
 182}
 183
 184/**
 185 *      wdtpci_ping:
 186 *
 187 *      Reload counter one with the watchdog heartbeat. We don't bother
 188 *      reloading the cascade counter.
 189 */
 190
 191static int wdtpci_ping(void)
 192{
 193        unsigned long flags;
 194
 195        spin_lock_irqsave(&wdtpci_lock, flags);
 196        /* Write a watchdog value */
 197        inb(WDT_DC);                    /* Disable watchdog */
 198        udelay(8);
 199        wdtpci_ctr_mode(1, 2);          /* Re-Program CTR1 for Mode 2:
 200                                                        Rate Generator */
 201        wdtpci_ctr_load(1, wd_heartbeat);/* Heartbeat */
 202        outb(0, WDT_DC);                /* Enable watchdog */
 203        udelay(8);
 204        spin_unlock_irqrestore(&wdtpci_lock, flags);
 205        return 0;
 206}
 207
 208/**
 209 *      wdtpci_set_heartbeat:
 210 *      @t:             the new heartbeat value that needs to be set.
 211 *
 212 *      Set a new heartbeat value for the watchdog device. If the heartbeat
 213 *      value is incorrect we keep the old value and return -EINVAL.
 214 *      If successful we return 0.
 215 */
 216static int wdtpci_set_heartbeat(int t)
 217{
 218        /* Arbitrary, can't find the card's limits */
 219        if (t < 1 || t > 65535)
 220                return -EINVAL;
 221
 222        heartbeat = t;
 223        wd_heartbeat = t * 100;
 224        return 0;
 225}
 226
 227/**
 228 *      wdtpci_get_status:
 229 *      @status:                the new status.
 230 *
 231 *      Extract the status information from a WDT watchdog device. There are
 232 *      several board variants so we have to know which bits are valid. Some
 233 *      bits default to one and some to zero in order to be maximally painful.
 234 *
 235 *      we then map the bits onto the status ioctl flags.
 236 */
 237
 238static int wdtpci_get_status(int *status)
 239{
 240        unsigned char new_status;
 241        unsigned long flags;
 242
 243        spin_lock_irqsave(&wdtpci_lock, flags);
 244        new_status = inb(WDT_SR);
 245        spin_unlock_irqrestore(&wdtpci_lock, flags);
 246
 247        *status = 0;
 248        if (new_status & WDC_SR_ISOI0)
 249                *status |= WDIOF_EXTERN1;
 250        if (new_status & WDC_SR_ISII1)
 251                *status |= WDIOF_EXTERN2;
 252        if (type == 501) {
 253                if (!(new_status & WDC_SR_TGOOD))
 254                        *status |= WDIOF_OVERHEAT;
 255                if (!(new_status & WDC_SR_PSUOVER))
 256                        *status |= WDIOF_POWEROVER;
 257                if (!(new_status & WDC_SR_PSUUNDR))
 258                        *status |= WDIOF_POWERUNDER;
 259                if (tachometer) {
 260                        if (!(new_status & WDC_SR_FANGOOD))
 261                                *status |= WDIOF_FANFAULT;
 262                }
 263        }
 264        return 0;
 265}
 266
 267/**
 268 *      wdtpci_get_temperature:
 269 *
 270 *      Reports the temperature in degrees Fahrenheit. The API is in
 271 *      farenheit. It was designed by an imperial measurement luddite.
 272 */
 273
 274static int wdtpci_get_temperature(int *temperature)
 275{
 276        unsigned short c;
 277        unsigned long flags;
 278        spin_lock_irqsave(&wdtpci_lock, flags);
 279        c = inb(WDT_RT);
 280        udelay(8);
 281        spin_unlock_irqrestore(&wdtpci_lock, flags);
 282        *temperature = (c * 11 / 15) + 7;
 283        return 0;
 284}
 285
 286/**
 287 *      wdtpci_interrupt:
 288 *      @irq:           Interrupt number
 289 *      @dev_id:        Unused as we don't allow multiple devices.
 290 *
 291 *      Handle an interrupt from the board. These are raised when the status
 292 *      map changes in what the board considers an interesting way. That means
 293 *      a failure condition occurring.
 294 */
 295
 296static irqreturn_t wdtpci_interrupt(int irq, void *dev_id)
 297{
 298        /*
 299         *      Read the status register see what is up and
 300         *      then printk it.
 301         */
 302        unsigned char status;
 303
 304        spin_lock(&wdtpci_lock);
 305
 306        status = inb(WDT_SR);
 307        udelay(8);
 308
 309        pr_crit("status %d\n", status);
 310
 311        if (type == 501) {
 312                if (!(status & WDC_SR_TGOOD)) {
 313                        pr_crit("Overheat alarm (%d)\n", inb(WDT_RT));
 314                        udelay(8);
 315                }
 316                if (!(status & WDC_SR_PSUOVER))
 317                        pr_crit("PSU over voltage\n");
 318                if (!(status & WDC_SR_PSUUNDR))
 319                        pr_crit("PSU under voltage\n");
 320                if (tachometer) {
 321                        if (!(status & WDC_SR_FANGOOD))
 322                                pr_crit("Possible fan fault\n");
 323                }
 324        }
 325        if (!(status & WDC_SR_WCCR)) {
 326#ifdef SOFTWARE_REBOOT
 327#ifdef ONLY_TESTING
 328                pr_crit("Would Reboot\n");
 329#else
 330                pr_crit("Initiating system reboot\n");
 331                emergency_restart();
 332#endif
 333#else
 334                pr_crit("Reset in 5ms\n");
 335#endif
 336        }
 337        spin_unlock(&wdtpci_lock);
 338        return IRQ_HANDLED;
 339}
 340
 341
 342/**
 343 *      wdtpci_write:
 344 *      @file: file handle to the watchdog
 345 *      @buf: buffer to write (unused as data does not matter here
 346 *      @count: count of bytes
 347 *      @ppos: pointer to the position to write. No seeks allowed
 348 *
 349 *      A write to a watchdog device is defined as a keepalive signal. Any
 350 *      write of data will do, as we we don't define content meaning.
 351 */
 352
 353static ssize_t wdtpci_write(struct file *file, const char __user *buf,
 354                                                size_t count, loff_t *ppos)
 355{
 356        if (count) {
 357                if (!nowayout) {
 358                        size_t i;
 359
 360                        /* In case it was set long ago */
 361                        expect_close = 0;
 362
 363                        for (i = 0; i != count; i++) {
 364                                char c;
 365                                if (get_user(c, buf + i))
 366                                        return -EFAULT;
 367                                if (c == 'V')
 368                                        expect_close = 42;
 369                        }
 370                }
 371                wdtpci_ping();
 372        }
 373        return count;
 374}
 375
 376/**
 377 *      wdtpci_ioctl:
 378 *      @file: file handle to the device
 379 *      @cmd: watchdog command
 380 *      @arg: argument pointer
 381 *
 382 *      The watchdog API defines a common set of functions for all watchdogs
 383 *      according to their available features. We only actually usefully support
 384 *      querying capabilities and current status.
 385 */
 386
 387static long wdtpci_ioctl(struct file *file, unsigned int cmd,
 388                                                        unsigned long arg)
 389{
 390        void __user *argp = (void __user *)arg;
 391        int __user *p = argp;
 392        int new_heartbeat;
 393        int status;
 394
 395        struct watchdog_info ident = {
 396                .options =              WDIOF_SETTIMEOUT|
 397                                        WDIOF_MAGICCLOSE|
 398                                        WDIOF_KEEPALIVEPING,
 399                .firmware_version =     1,
 400                .identity =             "PCI-WDT500/501",
 401        };
 402
 403        /* Add options according to the card we have */
 404        ident.options |= (WDIOF_EXTERN1|WDIOF_EXTERN2);
 405        if (type == 501) {
 406                ident.options |= (WDIOF_OVERHEAT|WDIOF_POWERUNDER|
 407                                                        WDIOF_POWEROVER);
 408                if (tachometer)
 409                        ident.options |= WDIOF_FANFAULT;
 410        }
 411
 412        switch (cmd) {
 413        case WDIOC_GETSUPPORT:
 414                return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
 415        case WDIOC_GETSTATUS:
 416                wdtpci_get_status(&status);
 417                return put_user(status, p);
 418        case WDIOC_GETBOOTSTATUS:
 419                return put_user(0, p);
 420        case WDIOC_KEEPALIVE:
 421                wdtpci_ping();
 422                return 0;
 423        case WDIOC_SETTIMEOUT:
 424                if (get_user(new_heartbeat, p))
 425                        return -EFAULT;
 426                if (wdtpci_set_heartbeat(new_heartbeat))
 427                        return -EINVAL;
 428                wdtpci_ping();
 429                fallthrough;
 430        case WDIOC_GETTIMEOUT:
 431                return put_user(heartbeat, p);
 432        default:
 433                return -ENOTTY;
 434        }
 435}
 436
 437/**
 438 *      wdtpci_open:
 439 *      @inode: inode of device
 440 *      @file: file handle to device
 441 *
 442 *      The watchdog device has been opened. The watchdog device is single
 443 *      open and on opening we load the counters. Counter zero is a 100Hz
 444 *      cascade, into counter 1 which downcounts to reboot. When the counter
 445 *      triggers counter 2 downcounts the length of the reset pulse which
 446 *      set set to be as long as possible.
 447 */
 448
 449static int wdtpci_open(struct inode *inode, struct file *file)
 450{
 451        if (test_and_set_bit(0, &open_lock))
 452                return -EBUSY;
 453
 454        if (nowayout)
 455                __module_get(THIS_MODULE);
 456        /*
 457         *      Activate
 458         */
 459        wdtpci_start();
 460        return stream_open(inode, file);
 461}
 462
 463/**
 464 *      wdtpci_release:
 465 *      @inode: inode to board
 466 *      @file: file handle to board
 467 *
 468 *      The watchdog has a configurable API. There is a religious dispute
 469 *      between people who want their watchdog to be able to shut down and
 470 *      those who want to be sure if the watchdog manager dies the machine
 471 *      reboots. In the former case we disable the counters, in the latter
 472 *      case you have to open it again very soon.
 473 */
 474
 475static int wdtpci_release(struct inode *inode, struct file *file)
 476{
 477        if (expect_close == 42) {
 478                wdtpci_stop();
 479        } else {
 480                pr_crit("Unexpected close, not stopping timer!\n");
 481                wdtpci_ping();
 482        }
 483        expect_close = 0;
 484        clear_bit(0, &open_lock);
 485        return 0;
 486}
 487
 488/**
 489 *      wdtpci_temp_read:
 490 *      @file: file handle to the watchdog board
 491 *      @buf: buffer to write 1 byte into
 492 *      @count: length of buffer
 493 *      @ptr: offset (no seek allowed)
 494 *
 495 *      Read reports the temperature in degrees Fahrenheit. The API is in
 496 *      fahrenheit. It was designed by an imperial measurement luddite.
 497 */
 498
 499static ssize_t wdtpci_temp_read(struct file *file, char __user *buf,
 500                                                size_t count, loff_t *ptr)
 501{
 502        int temperature;
 503
 504        if (wdtpci_get_temperature(&temperature))
 505                return -EFAULT;
 506
 507        if (copy_to_user(buf, &temperature, 1))
 508                return -EFAULT;
 509
 510        return 1;
 511}
 512
 513/**
 514 *      wdtpci_temp_open:
 515 *      @inode: inode of device
 516 *      @file: file handle to device
 517 *
 518 *      The temperature device has been opened.
 519 */
 520
 521static int wdtpci_temp_open(struct inode *inode, struct file *file)
 522{
 523        return stream_open(inode, file);
 524}
 525
 526/**
 527 *      wdtpci_temp_release:
 528 *      @inode: inode to board
 529 *      @file: file handle to board
 530 *
 531 *      The temperature device has been closed.
 532 */
 533
 534static int wdtpci_temp_release(struct inode *inode, struct file *file)
 535{
 536        return 0;
 537}
 538
 539/**
 540 *      wdtpci_notify_sys:
 541 *      @this: our notifier block
 542 *      @code: the event being reported
 543 *      @unused: unused
 544 *
 545 *      Our notifier is called on system shutdowns. We want to turn the card
 546 *      off at reboot otherwise the machine will reboot again during memory
 547 *      test or worse yet during the following fsck. This would suck, in fact
 548 *      trust me - if it happens it does suck.
 549 */
 550
 551static int wdtpci_notify_sys(struct notifier_block *this, unsigned long code,
 552                                                        void *unused)
 553{
 554        if (code == SYS_DOWN || code == SYS_HALT)
 555                wdtpci_stop();
 556        return NOTIFY_DONE;
 557}
 558
 559/*
 560 *      Kernel Interfaces
 561 */
 562
 563
 564static const struct file_operations wdtpci_fops = {
 565        .owner          = THIS_MODULE,
 566        .llseek         = no_llseek,
 567        .write          = wdtpci_write,
 568        .unlocked_ioctl = wdtpci_ioctl,
 569        .compat_ioctl   = compat_ptr_ioctl,
 570        .open           = wdtpci_open,
 571        .release        = wdtpci_release,
 572};
 573
 574static struct miscdevice wdtpci_miscdev = {
 575        .minor  = WATCHDOG_MINOR,
 576        .name   = "watchdog",
 577        .fops   = &wdtpci_fops,
 578};
 579
 580static const struct file_operations wdtpci_temp_fops = {
 581        .owner          = THIS_MODULE,
 582        .llseek         = no_llseek,
 583        .read           = wdtpci_temp_read,
 584        .open           = wdtpci_temp_open,
 585        .release        = wdtpci_temp_release,
 586};
 587
 588static struct miscdevice temp_miscdev = {
 589        .minor  = TEMP_MINOR,
 590        .name   = "temperature",
 591        .fops   = &wdtpci_temp_fops,
 592};
 593
 594/*
 595 *      The WDT card needs to learn about soft shutdowns in order to
 596 *      turn the timebomb registers off.
 597 */
 598
 599static struct notifier_block wdtpci_notifier = {
 600        .notifier_call = wdtpci_notify_sys,
 601};
 602
 603
 604static int wdtpci_init_one(struct pci_dev *dev,
 605                                        const struct pci_device_id *ent)
 606{
 607        int ret = -EIO;
 608
 609        dev_count++;
 610        if (dev_count > 1) {
 611                pr_err("This driver only supports one device\n");
 612                return -ENODEV;
 613        }
 614
 615        if (type != 500 && type != 501) {
 616                pr_err("unknown card type '%d'\n", type);
 617                return -ENODEV;
 618        }
 619
 620        if (pci_enable_device(dev)) {
 621                pr_err("Not possible to enable PCI Device\n");
 622                return -ENODEV;
 623        }
 624
 625        if (pci_resource_start(dev, 2) == 0x0000) {
 626                pr_err("No I/O-Address for card detected\n");
 627                ret = -ENODEV;
 628                goto out_pci;
 629        }
 630
 631        if (pci_request_region(dev, 2, "wdt_pci")) {
 632                pr_err("I/O address 0x%llx already in use\n",
 633                       (unsigned long long)pci_resource_start(dev, 2));
 634                goto out_pci;
 635        }
 636
 637        irq = dev->irq;
 638        io = pci_resource_start(dev, 2);
 639
 640        if (request_irq(irq, wdtpci_interrupt, IRQF_SHARED,
 641                         "wdt_pci", &wdtpci_miscdev)) {
 642                pr_err("IRQ %d is not free\n", irq);
 643                goto out_reg;
 644        }
 645
 646        pr_info("PCI-WDT500/501 (PCI-WDG-CSM) driver 0.10 at 0x%llx (Interrupt %d)\n",
 647                (unsigned long long)io, irq);
 648
 649        /* Check that the heartbeat value is within its range;
 650           if not reset to the default */
 651        if (wdtpci_set_heartbeat(heartbeat)) {
 652                wdtpci_set_heartbeat(WD_TIMO);
 653                pr_info("heartbeat value must be 0 < heartbeat < 65536, using %d\n",
 654                        WD_TIMO);
 655        }
 656
 657        ret = register_reboot_notifier(&wdtpci_notifier);
 658        if (ret) {
 659                pr_err("cannot register reboot notifier (err=%d)\n", ret);
 660                goto out_irq;
 661        }
 662
 663        if (type == 501) {
 664                ret = misc_register(&temp_miscdev);
 665                if (ret) {
 666                        pr_err("cannot register miscdev on minor=%d (err=%d)\n",
 667                               TEMP_MINOR, ret);
 668                        goto out_rbt;
 669                }
 670        }
 671
 672        ret = misc_register(&wdtpci_miscdev);
 673        if (ret) {
 674                pr_err("cannot register miscdev on minor=%d (err=%d)\n",
 675                       WATCHDOG_MINOR, ret);
 676                goto out_misc;
 677        }
 678
 679        pr_info("initialized. heartbeat=%d sec (nowayout=%d)\n",
 680                heartbeat, nowayout);
 681        if (type == 501)
 682                pr_info("Fan Tachometer is %s\n",
 683                        tachometer ? "Enabled" : "Disabled");
 684
 685        ret = 0;
 686out:
 687        return ret;
 688
 689out_misc:
 690        if (type == 501)
 691                misc_deregister(&temp_miscdev);
 692out_rbt:
 693        unregister_reboot_notifier(&wdtpci_notifier);
 694out_irq:
 695        free_irq(irq, &wdtpci_miscdev);
 696out_reg:
 697        pci_release_region(dev, 2);
 698out_pci:
 699        pci_disable_device(dev);
 700        goto out;
 701}
 702
 703
 704static void wdtpci_remove_one(struct pci_dev *pdev)
 705{
 706        /* here we assume only one device will ever have
 707         * been picked up and registered by probe function */
 708        misc_deregister(&wdtpci_miscdev);
 709        if (type == 501)
 710                misc_deregister(&temp_miscdev);
 711        unregister_reboot_notifier(&wdtpci_notifier);
 712        free_irq(irq, &wdtpci_miscdev);
 713        pci_release_region(pdev, 2);
 714        pci_disable_device(pdev);
 715        dev_count--;
 716}
 717
 718
 719static const struct pci_device_id wdtpci_pci_tbl[] = {
 720        {
 721                .vendor    = PCI_VENDOR_ID_ACCESSIO,
 722                .device    = PCI_DEVICE_ID_ACCESSIO_WDG_CSM,
 723                .subvendor = PCI_ANY_ID,
 724                .subdevice = PCI_ANY_ID,
 725        },
 726        { 0, }, /* terminate list */
 727};
 728MODULE_DEVICE_TABLE(pci, wdtpci_pci_tbl);
 729
 730
 731static struct pci_driver wdtpci_driver = {
 732        .name           = "wdt_pci",
 733        .id_table       = wdtpci_pci_tbl,
 734        .probe          = wdtpci_init_one,
 735        .remove         = wdtpci_remove_one,
 736};
 737
 738module_pci_driver(wdtpci_driver);
 739
 740MODULE_AUTHOR("JP Nollmann, Alan Cox");
 741MODULE_DESCRIPTION("Driver for the ICS PCI-WDT500/501 watchdog cards");
 742MODULE_LICENSE("GPL");
 743