X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fchar%2Fwatchdog%2Fi8xx_tco.c;h=e0627d79707b27f6b91d8ccb47506a29f1fad451;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=a13395e2c372a9b27355040c9c94eae21040992b;hpb=76828883507a47dae78837ab5dec5a5b4513c667;p=linux-2.6.git diff --git a/drivers/char/watchdog/i8xx_tco.c b/drivers/char/watchdog/i8xx_tco.c index a13395e2c..e0627d797 100644 --- a/drivers/char/watchdog/i8xx_tco.c +++ b/drivers/char/watchdog/i8xx_tco.c @@ -33,11 +33,6 @@ * 82801E (C-ICH) : document number 273599-001, 273645-002, * 82801EB (ICH5) : document number 252516-001, 252517-003, * 82801ER (ICH5R) : document number 252516-001, 252517-003, - * 82801FB (ICH6) : document number 301473-002, 301474-007, - * 82801FR (ICH6R) : document number 301473-002, 301474-007, - * 82801FBM (ICH6-M) : document number 301473-002, 301474-007, - * 82801FW (ICH6W) : document number 301473-001, 301474-007, - * 82801FRW (ICH6RW) : document number 301473-001, 301474-007 * * 20000710 Nils Faerber * Initial Version 0.01 @@ -66,6 +61,10 @@ * 20050807 Wim Van Sebroeck * 0.08 Make sure that the watchdog is only "armed" when started. * (Kernel Bug 4251) + * 20060416 Wim Van Sebroeck + * 0.09 Remove support for the ICH6, ICH6R, ICH6-M, ICH6W and ICH6RW and + * ICH7 chipsets. (See Kernel Bug 6031 - other code will support these + * chipsets) */ /* @@ -90,7 +89,7 @@ #include "i8xx_tco.h" /* Module and version information */ -#define TCO_VERSION "0.08" +#define TCO_VERSION "0.09" #define TCO_MODULE_NAME "i8xx TCO timer" #define TCO_DRIVER_NAME TCO_MODULE_NAME ", v" TCO_VERSION #define PFX TCO_MODULE_NAME ": " @@ -206,6 +205,23 @@ static int tco_timer_set_heartbeat (int t) return 0; } +static int tco_timer_get_timeleft (int *time_left) +{ + unsigned char val; + + spin_lock(&tco_lock); + + /* read the TCO Timer */ + val = inb (TCO1_RLD); + val &= 0x3f; + + spin_unlock(&tco_lock); + + *time_left = (int)((val * 6) / 10); + + return 0; +} + /* * /dev/watchdog handling */ @@ -273,6 +289,7 @@ static int i8xx_tco_ioctl (struct inode *inode, struct file *file, { int new_options, retval = -EINVAL; int new_heartbeat; + int time_left; void __user *argp = (void __user *)arg; int __user *p = argp; static struct watchdog_info ident = { @@ -321,7 +338,7 @@ static int i8xx_tco_ioctl (struct inode *inode, struct file *file, return -EFAULT; if (tco_timer_set_heartbeat(new_heartbeat)) - return -EINVAL; + return -EINVAL; tco_timer_keepalive (); /* Fall */ @@ -330,8 +347,16 @@ static int i8xx_tco_ioctl (struct inode *inode, struct file *file, case WDIOC_GETTIMEOUT: return put_user(heartbeat, p); + case WDIOC_GETTIMELEFT: + { + if (tco_timer_get_timeleft(&time_left)) + return -EINVAL; + + return put_user(time_left, p); + } + default: - return -ENOIOCTLCMD; + return -ENOTTY; } } @@ -353,7 +378,7 @@ static int i8xx_tco_notify_sys (struct notifier_block *this, unsigned long code, * Kernel Interfaces */ -static struct file_operations i8xx_tco_fops = { +static const struct file_operations i8xx_tco_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .write = i8xx_tco_write, @@ -381,23 +406,18 @@ static struct notifier_block i8xx_tco_notifier = { * want to register another driver on the same PCI id. */ static struct pci_device_id i8xx_tco_pci_tbl[] = { - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_0, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_0, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_10, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801E_0, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_0, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_2, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_1, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_1, PCI_ANY_ID, PCI_ANY_ID, }, - { 0, }, /* End of list */ + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_0) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_0) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_10) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801E_0) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_1) }, + { }, /* End of list */ }; MODULE_DEVICE_TABLE (pci, i8xx_tco_pci_tbl); @@ -414,12 +434,11 @@ static unsigned char __init i8xx_tco_getdevice (void) * Find the PCI device */ - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { + for_each_pci_dev(dev) if (pci_match_id(i8xx_tco_pci_tbl, dev)) { i8xx_tco_pci = dev; break; } - } if (i8xx_tco_pci) { /* @@ -434,6 +453,7 @@ static unsigned char __init i8xx_tco_getdevice (void) /* Something's wrong here, ACPIBASE has to be set */ if (badr == 0x0001 || badr == 0x0000) { printk (KERN_ERR PFX "failed to get TCOBASE address\n"); + pci_dev_put(i8xx_tco_pci); return 0; } @@ -445,6 +465,7 @@ static unsigned char __init i8xx_tco_getdevice (void) pci_read_config_byte (i8xx_tco_pci, 0xd4, &val1); if (val1 & 0x02) { printk (KERN_ERR PFX "failed to reset NO_REBOOT flag, reboot disabled by hardware\n"); + pci_dev_put(i8xx_tco_pci); return 0; /* Cannot reset NO_REBOOT bit */ } } @@ -456,6 +477,7 @@ static unsigned char __init i8xx_tco_getdevice (void) if (!request_region (SMI_EN + 1, 1, "i8xx TCO")) { printk (KERN_ERR PFX "I/O address 0x%04x already in use\n", SMI_EN + 1); + pci_dev_put(i8xx_tco_pci); return 0; } val1 = inb (SMI_EN + 1); @@ -522,6 +544,7 @@ unreg_notifier: unreg_region: release_region (TCOBASE, 0x10); out: + pci_dev_put(i8xx_tco_pci); return ret; } @@ -535,6 +558,8 @@ static void __exit watchdog_cleanup (void) misc_deregister (&i8xx_tco_miscdev); unregister_reboot_notifier(&i8xx_tco_notifier); release_region (TCOBASE, 0x10); + + pci_dev_put(i8xx_tco_pci); } module_init(watchdog_init);