Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  *  Industrial Computer Source PCI-WDT500/501 driver
0004  *
0005  *  (c) Copyright 1996-1997 Alan Cox <alan@lxorguk.ukuu.org.uk>,
0006  *                      All Rights Reserved.
0007  *
0008  *  Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
0009  *  warranty for any of this software. This material is provided
0010  *  "AS-IS" and at no charge.
0011  *
0012  *  (c) Copyright 1995    Alan Cox <alan@lxorguk.ukuu.org.uk>
0013  *
0014  *  Release 0.10.
0015  *
0016  *  Fixes
0017  *      Dave Gregorich  :   Modularisation and minor bugs
0018  *      Alan Cox    :   Added the watchdog ioctl() stuff
0019  *      Alan Cox    :   Fixed the reboot problem (as noted by
0020  *                  Matt Crocker).
0021  *      Alan Cox    :   Added wdt= boot option
0022  *      Alan Cox    :   Cleaned up copy/user stuff
0023  *      Tim Hockin  :   Added insmod parameters, comment cleanup
0024  *                  Parameterized timeout
0025  *      JP Nollmann :   Added support for PCI wdt501p
0026  *      Alan Cox    :   Split ISA and PCI cards into two drivers
0027  *      Jeff Garzik :   PCI cleanups
0028  *      Tigran Aivazian :   Restructured wdtpci_init_one() to handle
0029  *                  failures
0030  *      Joel Becker :   Added WDIOC_GET/SETTIMEOUT
0031  *      Zwane Mwaikambo :   Magic char closing, locking changes,
0032  *                  cleanups
0033  *      Matt Domsch :   nowayout module option
0034  */
0035 
0036 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0037 
0038 #include <linux/interrupt.h>
0039 #include <linux/module.h>
0040 #include <linux/moduleparam.h>
0041 #include <linux/types.h>
0042 #include <linux/miscdevice.h>
0043 #include <linux/watchdog.h>
0044 #include <linux/ioport.h>
0045 #include <linux/delay.h>
0046 #include <linux/notifier.h>
0047 #include <linux/reboot.h>
0048 #include <linux/fs.h>
0049 #include <linux/pci.h>
0050 #include <linux/io.h>
0051 #include <linux/uaccess.h>
0052 
0053 
0054 #define WDT_IS_PCI
0055 #include "wd501p.h"
0056 
0057 /* We can only use 1 card due to the /dev/watchdog restriction */
0058 static int dev_count;
0059 
0060 static unsigned long open_lock;
0061 static DEFINE_SPINLOCK(wdtpci_lock);
0062 static char expect_close;
0063 
0064 static resource_size_t io;
0065 static int irq;
0066 
0067 /* Default timeout */
0068 #define WD_TIMO 60          /* Default heartbeat = 60 seconds */
0069 
0070 static int heartbeat = WD_TIMO;
0071 static int wd_heartbeat;
0072 module_param(heartbeat, int, 0);
0073 MODULE_PARM_DESC(heartbeat,
0074         "Watchdog heartbeat in seconds. (0<heartbeat<65536, default="
0075                 __MODULE_STRING(WD_TIMO) ")");
0076 
0077 static bool nowayout = WATCHDOG_NOWAYOUT;
0078 module_param(nowayout, bool, 0);
0079 MODULE_PARM_DESC(nowayout,
0080         "Watchdog cannot be stopped once started (default="
0081                 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
0082 
0083 /* Support for the Fan Tachometer on the PCI-WDT501 */
0084 static int tachometer;
0085 module_param(tachometer, int, 0);
0086 MODULE_PARM_DESC(tachometer,
0087         "PCI-WDT501 Fan Tachometer support (0=disable, default=0)");
0088 
0089 static int type = 500;
0090 module_param(type, int, 0);
0091 MODULE_PARM_DESC(type,
0092         "PCI-WDT501 Card type (500 or 501 , default=500)");
0093 
0094 /*
0095  *  Programming support
0096  */
0097 
0098 static void wdtpci_ctr_mode(int ctr, int mode)
0099 {
0100     ctr <<= 6;
0101     ctr |= 0x30;
0102     ctr |= (mode << 1);
0103     outb(ctr, WDT_CR);
0104     udelay(8);
0105 }
0106 
0107 static void wdtpci_ctr_load(int ctr, int val)
0108 {
0109     outb(val & 0xFF, WDT_COUNT0 + ctr);
0110     udelay(8);
0111     outb(val >> 8, WDT_COUNT0 + ctr);
0112     udelay(8);
0113 }
0114 
0115 /**
0116  *  wdtpci_start:
0117  *
0118  *  Start the watchdog driver.
0119  */
0120 
0121 static int wdtpci_start(void)
0122 {
0123     unsigned long flags;
0124 
0125     spin_lock_irqsave(&wdtpci_lock, flags);
0126 
0127     /*
0128      * "pet" the watchdog, as Access says.
0129      * This resets the clock outputs.
0130      */
0131     inb(WDT_DC);            /* Disable watchdog */
0132     udelay(8);
0133     wdtpci_ctr_mode(2, 0);      /* Program CTR2 for Mode 0:
0134                         Pulse on Terminal Count */
0135     outb(0, WDT_DC);        /* Enable watchdog */
0136     udelay(8);
0137     inb(WDT_DC);            /* Disable watchdog */
0138     udelay(8);
0139     outb(0, WDT_CLOCK);     /* 2.0833MHz clock */
0140     udelay(8);
0141     inb(WDT_BUZZER);        /* disable */
0142     udelay(8);
0143     inb(WDT_OPTONOTRST);        /* disable */
0144     udelay(8);
0145     inb(WDT_OPTORST);       /* disable */
0146     udelay(8);
0147     inb(WDT_PROGOUT);       /* disable */
0148     udelay(8);
0149     wdtpci_ctr_mode(0, 3);      /* Program CTR0 for Mode 3:
0150                         Square Wave Generator */
0151     wdtpci_ctr_mode(1, 2);      /* Program CTR1 for Mode 2:
0152                         Rate Generator */
0153     wdtpci_ctr_mode(2, 1);      /* Program CTR2 for Mode 1:
0154                         Retriggerable One-Shot */
0155     wdtpci_ctr_load(0, 20833);  /* count at 100Hz */
0156     wdtpci_ctr_load(1, wd_heartbeat);/* Heartbeat */
0157     /* DO NOT LOAD CTR2 on PCI card! -- JPN */
0158     outb(0, WDT_DC);        /* Enable watchdog */
0159     udelay(8);
0160 
0161     spin_unlock_irqrestore(&wdtpci_lock, flags);
0162     return 0;
0163 }
0164 
0165 /**
0166  *  wdtpci_stop:
0167  *
0168  *  Stop the watchdog driver.
0169  */
0170 
0171 static int wdtpci_stop(void)
0172 {
0173     unsigned long flags;
0174 
0175     /* Turn the card off */
0176     spin_lock_irqsave(&wdtpci_lock, flags);
0177     inb(WDT_DC);            /* Disable watchdog */
0178     udelay(8);
0179     wdtpci_ctr_load(2, 0);      /* 0 length reset pulses now */
0180     spin_unlock_irqrestore(&wdtpci_lock, flags);
0181     return 0;
0182 }
0183 
0184 /**
0185  *  wdtpci_ping:
0186  *
0187  *  Reload counter one with the watchdog heartbeat. We don't bother
0188  *  reloading the cascade counter.
0189  */
0190 
0191 static int wdtpci_ping(void)
0192 {
0193     unsigned long flags;
0194 
0195     spin_lock_irqsave(&wdtpci_lock, flags);
0196     /* Write a watchdog value */
0197     inb(WDT_DC);            /* Disable watchdog */
0198     udelay(8);
0199     wdtpci_ctr_mode(1, 2);      /* Re-Program CTR1 for Mode 2:
0200                             Rate Generator */
0201     wdtpci_ctr_load(1, wd_heartbeat);/* Heartbeat */
0202     outb(0, WDT_DC);        /* Enable watchdog */
0203     udelay(8);
0204     spin_unlock_irqrestore(&wdtpci_lock, flags);
0205     return 0;
0206 }
0207 
0208 /**
0209  *  wdtpci_set_heartbeat:
0210  *  @t:     the new heartbeat value that needs to be set.
0211  *
0212  *  Set a new heartbeat value for the watchdog device. If the heartbeat
0213  *  value is incorrect we keep the old value and return -EINVAL.
0214  *  If successful we return 0.
0215  */
0216 static int wdtpci_set_heartbeat(int t)
0217 {
0218     /* Arbitrary, can't find the card's limits */
0219     if (t < 1 || t > 65535)
0220         return -EINVAL;
0221 
0222     heartbeat = t;
0223     wd_heartbeat = t * 100;
0224     return 0;
0225 }
0226 
0227 /**
0228  *  wdtpci_get_status:
0229  *  @status:        the new status.
0230  *
0231  *  Extract the status information from a WDT watchdog device. There are
0232  *  several board variants so we have to know which bits are valid. Some
0233  *  bits default to one and some to zero in order to be maximally painful.
0234  *
0235  *  we then map the bits onto the status ioctl flags.
0236  */
0237 
0238 static int wdtpci_get_status(int *status)
0239 {
0240     unsigned char new_status;
0241     unsigned long flags;
0242 
0243     spin_lock_irqsave(&wdtpci_lock, flags);
0244     new_status = inb(WDT_SR);
0245     spin_unlock_irqrestore(&wdtpci_lock, flags);
0246 
0247     *status = 0;
0248     if (new_status & WDC_SR_ISOI0)
0249         *status |= WDIOF_EXTERN1;
0250     if (new_status & WDC_SR_ISII1)
0251         *status |= WDIOF_EXTERN2;
0252     if (type == 501) {
0253         if (!(new_status & WDC_SR_TGOOD))
0254             *status |= WDIOF_OVERHEAT;
0255         if (!(new_status & WDC_SR_PSUOVER))
0256             *status |= WDIOF_POWEROVER;
0257         if (!(new_status & WDC_SR_PSUUNDR))
0258             *status |= WDIOF_POWERUNDER;
0259         if (tachometer) {
0260             if (!(new_status & WDC_SR_FANGOOD))
0261                 *status |= WDIOF_FANFAULT;
0262         }
0263     }
0264     return 0;
0265 }
0266 
0267 /**
0268  *  wdtpci_get_temperature:
0269  *
0270  *  Reports the temperature in degrees Fahrenheit. The API is in
0271  *  farenheit. It was designed by an imperial measurement luddite.
0272  */
0273 
0274 static int wdtpci_get_temperature(int *temperature)
0275 {
0276     unsigned short c;
0277     unsigned long flags;
0278     spin_lock_irqsave(&wdtpci_lock, flags);
0279     c = inb(WDT_RT);
0280     udelay(8);
0281     spin_unlock_irqrestore(&wdtpci_lock, flags);
0282     *temperature = (c * 11 / 15) + 7;
0283     return 0;
0284 }
0285 
0286 /**
0287  *  wdtpci_interrupt:
0288  *  @irq:       Interrupt number
0289  *  @dev_id:    Unused as we don't allow multiple devices.
0290  *
0291  *  Handle an interrupt from the board. These are raised when the status
0292  *  map changes in what the board considers an interesting way. That means
0293  *  a failure condition occurring.
0294  */
0295 
0296 static irqreturn_t wdtpci_interrupt(int irq, void *dev_id)
0297 {
0298     /*
0299      *  Read the status register see what is up and
0300      *  then printk it.
0301      */
0302     unsigned char status;
0303 
0304     spin_lock(&wdtpci_lock);
0305 
0306     status = inb(WDT_SR);
0307     udelay(8);
0308 
0309     pr_crit("status %d\n", status);
0310 
0311     if (type == 501) {
0312         if (!(status & WDC_SR_TGOOD)) {
0313             pr_crit("Overheat alarm (%d)\n", inb(WDT_RT));
0314             udelay(8);
0315         }
0316         if (!(status & WDC_SR_PSUOVER))
0317             pr_crit("PSU over voltage\n");
0318         if (!(status & WDC_SR_PSUUNDR))
0319             pr_crit("PSU under voltage\n");
0320         if (tachometer) {
0321             if (!(status & WDC_SR_FANGOOD))
0322                 pr_crit("Possible fan fault\n");
0323         }
0324     }
0325     if (!(status & WDC_SR_WCCR)) {
0326 #ifdef SOFTWARE_REBOOT
0327 #ifdef ONLY_TESTING
0328         pr_crit("Would Reboot\n");
0329 #else
0330         pr_crit("Initiating system reboot\n");
0331         emergency_restart();
0332 #endif
0333 #else
0334         pr_crit("Reset in 5ms\n");
0335 #endif
0336     }
0337     spin_unlock(&wdtpci_lock);
0338     return IRQ_HANDLED;
0339 }
0340 
0341 
0342 /**
0343  *  wdtpci_write:
0344  *  @file: file handle to the watchdog
0345  *  @buf: buffer to write (unused as data does not matter here
0346  *  @count: count of bytes
0347  *  @ppos: pointer to the position to write. No seeks allowed
0348  *
0349  *  A write to a watchdog device is defined as a keepalive signal. Any
0350  *  write of data will do, as we we don't define content meaning.
0351  */
0352 
0353 static ssize_t wdtpci_write(struct file *file, const char __user *buf,
0354                         size_t count, loff_t *ppos)
0355 {
0356     if (count) {
0357         if (!nowayout) {
0358             size_t i;
0359 
0360             /* In case it was set long ago */
0361             expect_close = 0;
0362 
0363             for (i = 0; i != count; i++) {
0364                 char c;
0365                 if (get_user(c, buf + i))
0366                     return -EFAULT;
0367                 if (c == 'V')
0368                     expect_close = 42;
0369             }
0370         }
0371         wdtpci_ping();
0372     }
0373     return count;
0374 }
0375 
0376 /**
0377  *  wdtpci_ioctl:
0378  *  @file: file handle to the device
0379  *  @cmd: watchdog command
0380  *  @arg: argument pointer
0381  *
0382  *  The watchdog API defines a common set of functions for all watchdogs
0383  *  according to their available features. We only actually usefully support
0384  *  querying capabilities and current status.
0385  */
0386 
0387 static long wdtpci_ioctl(struct file *file, unsigned int cmd,
0388                             unsigned long arg)
0389 {
0390     void __user *argp = (void __user *)arg;
0391     int __user *p = argp;
0392     int new_heartbeat;
0393     int status;
0394 
0395     struct watchdog_info ident = {
0396         .options =      WDIOF_SETTIMEOUT|
0397                     WDIOF_MAGICCLOSE|
0398                     WDIOF_KEEPALIVEPING,
0399         .firmware_version = 1,
0400         .identity =     "PCI-WDT500/501",
0401     };
0402 
0403     /* Add options according to the card we have */
0404     ident.options |= (WDIOF_EXTERN1|WDIOF_EXTERN2);
0405     if (type == 501) {
0406         ident.options |= (WDIOF_OVERHEAT|WDIOF_POWERUNDER|
0407                             WDIOF_POWEROVER);
0408         if (tachometer)
0409             ident.options |= WDIOF_FANFAULT;
0410     }
0411 
0412     switch (cmd) {
0413     case WDIOC_GETSUPPORT:
0414         return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
0415     case WDIOC_GETSTATUS:
0416         wdtpci_get_status(&status);
0417         return put_user(status, p);
0418     case WDIOC_GETBOOTSTATUS:
0419         return put_user(0, p);
0420     case WDIOC_KEEPALIVE:
0421         wdtpci_ping();
0422         return 0;
0423     case WDIOC_SETTIMEOUT:
0424         if (get_user(new_heartbeat, p))
0425             return -EFAULT;
0426         if (wdtpci_set_heartbeat(new_heartbeat))
0427             return -EINVAL;
0428         wdtpci_ping();
0429         fallthrough;
0430     case WDIOC_GETTIMEOUT:
0431         return put_user(heartbeat, p);
0432     default:
0433         return -ENOTTY;
0434     }
0435 }
0436 
0437 /**
0438  *  wdtpci_open:
0439  *  @inode: inode of device
0440  *  @file: file handle to device
0441  *
0442  *  The watchdog device has been opened. The watchdog device is single
0443  *  open and on opening we load the counters. Counter zero is a 100Hz
0444  *  cascade, into counter 1 which downcounts to reboot. When the counter
0445  *  triggers counter 2 downcounts the length of the reset pulse which
0446  *  set set to be as long as possible.
0447  */
0448 
0449 static int wdtpci_open(struct inode *inode, struct file *file)
0450 {
0451     if (test_and_set_bit(0, &open_lock))
0452         return -EBUSY;
0453 
0454     if (nowayout)
0455         __module_get(THIS_MODULE);
0456     /*
0457      *  Activate
0458      */
0459     wdtpci_start();
0460     return stream_open(inode, file);
0461 }
0462 
0463 /**
0464  *  wdtpci_release:
0465  *  @inode: inode to board
0466  *  @file: file handle to board
0467  *
0468  *  The watchdog has a configurable API. There is a religious dispute
0469  *  between people who want their watchdog to be able to shut down and
0470  *  those who want to be sure if the watchdog manager dies the machine
0471  *  reboots. In the former case we disable the counters, in the latter
0472  *  case you have to open it again very soon.
0473  */
0474 
0475 static int wdtpci_release(struct inode *inode, struct file *file)
0476 {
0477     if (expect_close == 42) {
0478         wdtpci_stop();
0479     } else {
0480         pr_crit("Unexpected close, not stopping timer!\n");
0481         wdtpci_ping();
0482     }
0483     expect_close = 0;
0484     clear_bit(0, &open_lock);
0485     return 0;
0486 }
0487 
0488 /**
0489  *  wdtpci_temp_read:
0490  *  @file: file handle to the watchdog board
0491  *  @buf: buffer to write 1 byte into
0492  *  @count: length of buffer
0493  *  @ptr: offset (no seek allowed)
0494  *
0495  *  Read reports the temperature in degrees Fahrenheit. The API is in
0496  *  fahrenheit. It was designed by an imperial measurement luddite.
0497  */
0498 
0499 static ssize_t wdtpci_temp_read(struct file *file, char __user *buf,
0500                         size_t count, loff_t *ptr)
0501 {
0502     int temperature;
0503 
0504     if (wdtpci_get_temperature(&temperature))
0505         return -EFAULT;
0506 
0507     if (copy_to_user(buf, &temperature, 1))
0508         return -EFAULT;
0509 
0510     return 1;
0511 }
0512 
0513 /**
0514  *  wdtpci_temp_open:
0515  *  @inode: inode of device
0516  *  @file: file handle to device
0517  *
0518  *  The temperature device has been opened.
0519  */
0520 
0521 static int wdtpci_temp_open(struct inode *inode, struct file *file)
0522 {
0523     return stream_open(inode, file);
0524 }
0525 
0526 /**
0527  *  wdtpci_temp_release:
0528  *  @inode: inode to board
0529  *  @file: file handle to board
0530  *
0531  *  The temperature device has been closed.
0532  */
0533 
0534 static int wdtpci_temp_release(struct inode *inode, struct file *file)
0535 {
0536     return 0;
0537 }
0538 
0539 /**
0540  *  wdtpci_notify_sys:
0541  *  @this: our notifier block
0542  *  @code: the event being reported
0543  *  @unused: unused
0544  *
0545  *  Our notifier is called on system shutdowns. We want to turn the card
0546  *  off at reboot otherwise the machine will reboot again during memory
0547  *  test or worse yet during the following fsck. This would suck, in fact
0548  *  trust me - if it happens it does suck.
0549  */
0550 
0551 static int wdtpci_notify_sys(struct notifier_block *this, unsigned long code,
0552                             void *unused)
0553 {
0554     if (code == SYS_DOWN || code == SYS_HALT)
0555         wdtpci_stop();
0556     return NOTIFY_DONE;
0557 }
0558 
0559 /*
0560  *  Kernel Interfaces
0561  */
0562 
0563 
0564 static const struct file_operations wdtpci_fops = {
0565     .owner      = THIS_MODULE,
0566     .llseek     = no_llseek,
0567     .write      = wdtpci_write,
0568     .unlocked_ioctl = wdtpci_ioctl,
0569     .compat_ioctl   = compat_ptr_ioctl,
0570     .open       = wdtpci_open,
0571     .release    = wdtpci_release,
0572 };
0573 
0574 static struct miscdevice wdtpci_miscdev = {
0575     .minor  = WATCHDOG_MINOR,
0576     .name   = "watchdog",
0577     .fops   = &wdtpci_fops,
0578 };
0579 
0580 static const struct file_operations wdtpci_temp_fops = {
0581     .owner      = THIS_MODULE,
0582     .llseek     = no_llseek,
0583     .read       = wdtpci_temp_read,
0584     .open       = wdtpci_temp_open,
0585     .release    = wdtpci_temp_release,
0586 };
0587 
0588 static struct miscdevice temp_miscdev = {
0589     .minor  = TEMP_MINOR,
0590     .name   = "temperature",
0591     .fops   = &wdtpci_temp_fops,
0592 };
0593 
0594 /*
0595  *  The WDT card needs to learn about soft shutdowns in order to
0596  *  turn the timebomb registers off.
0597  */
0598 
0599 static struct notifier_block wdtpci_notifier = {
0600     .notifier_call = wdtpci_notify_sys,
0601 };
0602 
0603 
0604 static int wdtpci_init_one(struct pci_dev *dev,
0605                     const struct pci_device_id *ent)
0606 {
0607     int ret = -EIO;
0608 
0609     dev_count++;
0610     if (dev_count > 1) {
0611         pr_err("This driver only supports one device\n");
0612         return -ENODEV;
0613     }
0614 
0615     if (type != 500 && type != 501) {
0616         pr_err("unknown card type '%d'\n", type);
0617         return -ENODEV;
0618     }
0619 
0620     if (pci_enable_device(dev)) {
0621         pr_err("Not possible to enable PCI Device\n");
0622         return -ENODEV;
0623     }
0624 
0625     if (pci_resource_start(dev, 2) == 0x0000) {
0626         pr_err("No I/O-Address for card detected\n");
0627         ret = -ENODEV;
0628         goto out_pci;
0629     }
0630 
0631     if (pci_request_region(dev, 2, "wdt_pci")) {
0632         pr_err("I/O address 0x%llx already in use\n",
0633                (unsigned long long)pci_resource_start(dev, 2));
0634         goto out_pci;
0635     }
0636 
0637     irq = dev->irq;
0638     io = pci_resource_start(dev, 2);
0639 
0640     if (request_irq(irq, wdtpci_interrupt, IRQF_SHARED,
0641              "wdt_pci", &wdtpci_miscdev)) {
0642         pr_err("IRQ %d is not free\n", irq);
0643         goto out_reg;
0644     }
0645 
0646     pr_info("PCI-WDT500/501 (PCI-WDG-CSM) driver 0.10 at 0x%llx (Interrupt %d)\n",
0647         (unsigned long long)io, irq);
0648 
0649     /* Check that the heartbeat value is within its range;
0650        if not reset to the default */
0651     if (wdtpci_set_heartbeat(heartbeat)) {
0652         wdtpci_set_heartbeat(WD_TIMO);
0653         pr_info("heartbeat value must be 0 < heartbeat < 65536, using %d\n",
0654             WD_TIMO);
0655     }
0656 
0657     ret = register_reboot_notifier(&wdtpci_notifier);
0658     if (ret) {
0659         pr_err("cannot register reboot notifier (err=%d)\n", ret);
0660         goto out_irq;
0661     }
0662 
0663     if (type == 501) {
0664         ret = misc_register(&temp_miscdev);
0665         if (ret) {
0666             pr_err("cannot register miscdev on minor=%d (err=%d)\n",
0667                    TEMP_MINOR, ret);
0668             goto out_rbt;
0669         }
0670     }
0671 
0672     ret = misc_register(&wdtpci_miscdev);
0673     if (ret) {
0674         pr_err("cannot register miscdev on minor=%d (err=%d)\n",
0675                WATCHDOG_MINOR, ret);
0676         goto out_misc;
0677     }
0678 
0679     pr_info("initialized. heartbeat=%d sec (nowayout=%d)\n",
0680         heartbeat, nowayout);
0681     if (type == 501)
0682         pr_info("Fan Tachometer is %s\n",
0683             tachometer ? "Enabled" : "Disabled");
0684 
0685     ret = 0;
0686 out:
0687     return ret;
0688 
0689 out_misc:
0690     if (type == 501)
0691         misc_deregister(&temp_miscdev);
0692 out_rbt:
0693     unregister_reboot_notifier(&wdtpci_notifier);
0694 out_irq:
0695     free_irq(irq, &wdtpci_miscdev);
0696 out_reg:
0697     pci_release_region(dev, 2);
0698 out_pci:
0699     pci_disable_device(dev);
0700     goto out;
0701 }
0702 
0703 
0704 static void wdtpci_remove_one(struct pci_dev *pdev)
0705 {
0706     /* here we assume only one device will ever have
0707      * been picked up and registered by probe function */
0708     misc_deregister(&wdtpci_miscdev);
0709     if (type == 501)
0710         misc_deregister(&temp_miscdev);
0711     unregister_reboot_notifier(&wdtpci_notifier);
0712     free_irq(irq, &wdtpci_miscdev);
0713     pci_release_region(pdev, 2);
0714     pci_disable_device(pdev);
0715     dev_count--;
0716 }
0717 
0718 
0719 static const struct pci_device_id wdtpci_pci_tbl[] = {
0720     {
0721         .vendor    = PCI_VENDOR_ID_ACCESSIO,
0722         .device    = PCI_DEVICE_ID_ACCESSIO_WDG_CSM,
0723         .subvendor = PCI_ANY_ID,
0724         .subdevice = PCI_ANY_ID,
0725     },
0726     { 0, }, /* terminate list */
0727 };
0728 MODULE_DEVICE_TABLE(pci, wdtpci_pci_tbl);
0729 
0730 
0731 static struct pci_driver wdtpci_driver = {
0732     .name       = "wdt_pci",
0733     .id_table   = wdtpci_pci_tbl,
0734     .probe      = wdtpci_init_one,
0735     .remove     = wdtpci_remove_one,
0736 };
0737 
0738 module_pci_driver(wdtpci_driver);
0739 
0740 MODULE_AUTHOR("JP Nollmann, Alan Cox");
0741 MODULE_DESCRIPTION("Driver for the ICS PCI-WDT500/501 watchdog cards");
0742 MODULE_LICENSE("GPL");