static long iTCO_wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { int new_options, retval = -EINVAL; int new_heartbeat; void __user *argp = (void __user *)arg; int __user *p = argp; static const struct watchdog_info ident = { .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, .firmware_version = 0, .identity = DRV_NAME, }; switch (cmd) { case WDIOC_GETSUPPORT: return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; case WDIOC_GETSTATUS: case WDIOC_GETBOOTSTATUS: return put_user(0, p); case WDIOC_SETOPTIONS: { if (get_user(new_options, p)) return -EFAULT; if (new_options & WDIOS_DISABLECARD) { iTCO_wdt_stop(); retval = 0; } if (new_options & WDIOS_ENABLECARD) { iTCO_wdt_keepalive(); iTCO_wdt_start(); retval = 0; } return retval; } case WDIOC_KEEPALIVE: iTCO_wdt_keepalive(); return 0; case WDIOC_SETTIMEOUT: { if (get_user(new_heartbeat, p)) return -EFAULT; if (iTCO_wdt_set_heartbeat(new_heartbeat)) return -EINVAL; iTCO_wdt_keepalive(); /* Fall */ } case WDIOC_GETTIMEOUT: return put_user(heartbeat, p); case WDIOC_GETTIMELEFT: { int time_left; if (iTCO_wdt_get_timeleft(&time_left)) return -EINVAL; return put_user(time_left, p); } default: return -ENOTTY; } } /* * Kernel Interfaces */ static const struct file_operations iTCO_wdt_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .write = iTCO_wdt_write, .unlocked_ioctl = iTCO_wdt_ioctl, .open = iTCO_wdt_open, .release = iTCO_wdt_release, }; static struct miscdevice iTCO_wdt_miscdev = { .minor = WATCHDOG_MINOR, .name = "watchdog", .fops = &iTCO_wdt_fops, }; /* * Reboot notifier */ static int TCO_reboot_notifier(struct notifier_block *this, unsigned long code, void *another_unused) { if (code == SYS_HALT || code == SYS_POWER_OFF) { iTCO_wdt_set_reset_type(TCO_POLICY_HALT); } iTCO_wdt_last_kick(5); #ifdef CONFIG_DEBUG_FS if (iTCO_wdt_private.panic_reboot_notifier) { BUG(); } #endif return NOTIFY_DONE; } static irqreturn_t tco_irq_handler(int irq, void *arg) { unsigned long val32; pr_warn("[SHTDWN] %s, WATCHDOG TIMEOUT HANDLER!\n", __func__); /* reduce the timeout to the minimum, but sufficient for tracing */ iTCO_wdt_set_heartbeat(15); iTCO_wdt_keepalive(); trigger_all_cpu_backtrace(); panic("Kernel Watchdog"); /* This code should not be reached */ return IRQ_HANDLED; } /* * Init & exit routines */ static int iTCO_wdt_init(struct pci_dev *pdev, const struct pci_device_id *ent, struct platform_device *dev) { int ret; u32 base_address; unsigned long val32; /* * Find the ACPI/PM base I/O address which is the base * for the TCO registers (TCOBASE=ACPIBASE + 0x60) * ACPIBASE is bits [15:7] from 0x40-0x43 */ pci_read_config_dword(pdev, 0x40, &base_address); base_address &= 0x0000ff80; if (base_address == 0x00000000) { /* Something's wrong here, ACPIBASE has to be set */ pr_err("failed to get TCOBASE address, device disabled by hardware/BIOS\n"); return -ENODEV; } iTCO_wdt_private.iTCO_version = iTCO_chipset_info[ent->driver_data].iTCO_version; iTCO_wdt_private.ACPIBASE = base_address; iTCO_wdt_private.pdev = pdev; pci_read_config_dword(pdev, 0x44, &pmc_base_address); pmc_base_address &= 0xFFFFFE00; /* * Disable watchdog on command-line demand */ if (strstr(saved_command_line, "disable_kernel_watchdog=1")) { pr_warn("disable_kernel_watchdog=1 watchdog will not be started\n"); iTCO_wdt_private.enable = false; /* Set the NO_REBOOT bit to prevent later reboots */ iTCO_wdt_set_NO_REBOOT_bit(); /* Ensure Wdt is well stopped in case started by IAFW */ iTCO_wdt_stop(); } else { iTCO_wdt_private.enable = true; /* Check chipset's NO_REBOOT bit */ if (iTCO_wdt_unset_NO_REBOOT_bit()) { pr_err("unable to reset NO_REBOOT flag, device disabled by hardware/BIOS\n"); ret = -ENODEV; /* Cannot reset NO_REBOOT bit */ goto out; } } /* The TCO logic uses the TCO_EN bit in the SMI_EN register */ if (!request_region(SMI_EN, 4, "iTCO_wdt")) { pr_err("I/O address 0x%04lx already in use, device disabled\n", SMI_EN); ret = -EIO; goto out; } if (!request_region(SMI_STS, 4, "iTCO_wdt")) { pr_err("I/O address 0x%04lx already in use, device disabled\n", SMI_STS); ret = -EIO; goto unreg_smi_sts; } if (turn_SMI_watchdog_clear_off >= iTCO_wdt_private.iTCO_version) { /* Bit 13: TCO_EN -> 0 = Disables TCO logic generating an SMI# */ val32 = inl(SMI_EN); val32 &= ~TCO_EN_BIT; /* Turn off TCO watchdog timer */ outl(val32, SMI_EN); } /* The TCO I/O registers reside in a 32-byte range pointed to by the TCOBASE value */ if (!request_region(TCOBASE, 0x20, "iTCO_wdt")) { pr_err("I/O address 0x%04lx already in use, device disabled\n", TCOBASE); ret = -EIO; goto unreg_smi_en; } pr_info("Found a %s TCO device (Version=%d, TCOBASE=0x%04lx)\n", iTCO_chipset_info[ent->driver_data].name, iTCO_chipset_info[ent->driver_data].iTCO_version, TCOBASE); /* Check that the heartbeat value is within it's range; if not reset to the default */ if (iTCO_wdt_set_heartbeat(heartbeat)) { iTCO_wdt_set_heartbeat(WATCHDOG_HEARTBEAT); pr_info("timeout value out of range, using %d\n", heartbeat); } ret = misc_register(&iTCO_wdt_miscdev); if (ret != 0) { pr_err("cannot register miscdev on minor=%d (err=%d)\n", WATCHDOG_MINOR, ret); goto unreg_region; } pr_info("initialized. heartbeat=%d sec (nowayout=%d)\n", heartbeat, nowayout); /* Reset OS policy */ iTCO_wdt_set_reset_type(TCO_POLICY_NORM); ret = acpi_register_gsi(NULL, TCO_WARNING_IRQ, ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_HIGH); if (ret < 0) { pr_err("failed to configure TCO warning IRQ %d\n", TCO_WARNING_IRQ); goto misc_unreg; } ret = request_irq(TCO_WARNING_IRQ, tco_irq_handler, 0, "tco_watchdog", NULL); if (ret < 0) { pr_err("failed to request TCO warning IRQ %d\n", TCO_WARNING_IRQ); goto gsi_unreg; } /* Clear old TCO timeout status */ val32 = TCO_TIMEOUT_BIT | SECOND_TO_STS_BIT; outl(val32, TCO1_STS); /* Clear the SMI status */ outl(TCO_STS_BIT, SMI_STS); /* Enable SMI for TCO */ val32 = inl(SMI_EN); val32 |= TCO_EN_BIT; outl(val32, SMI_EN); /* then ensure that PMC is ready to handle next SMI */ val32 |= EOS_BIT; outl(val32, SMI_EN); reboot_notifier.notifier_call = TCO_reboot_notifier; reboot_notifier.priority = 1; ret = register_reboot_notifier(&reboot_notifier); if (ret) /* We continue as reboot notifier is not critical for * watchdog */ pr_err("cannot register reboot notifier %d\n", ret); return 0; gsi_unreg: acpi_unregister_gsi(TCO_WARNING_IRQ); misc_unreg: misc_deregister(&iTCO_wdt_miscdev); unreg_region: release_region(TCOBASE, 0x20); unreg_smi_sts: release_region(SMI_STS, 4); unreg_smi_en: release_region(SMI_EN, 4); out: iTCO_wdt_private.ACPIBASE = 0; return ret; }
static void install_reboot_notifier(void) { register_reboot_notifier(&reboot_boot_globals_nb); }
static int __init sc1200wdt_init(void) { int ret; printk("%s\n", banner); sema_init(&open_sem, 1); #if defined CONFIG_PNP if (isapnp) { ret = pnp_register_driver(&scl200wdt_pnp_driver); if (ret) goto out_clean; } #endif if (io == -1) { printk(KERN_ERR PFX "io parameter must be specified\n"); ret = -EINVAL; goto out_pnp; } #if defined CONFIG_PNP /* now that the user has specified an IO port and we haven't detected * any devices, disable pnp support */ isapnp = 0; pnp_unregister_driver(&scl200wdt_pnp_driver); #endif if (!request_region(io, io_len, SC1200_MODULE_NAME)) { printk(KERN_ERR PFX "Unable to register IO port %#x\n", io); ret = -EBUSY; goto out_pnp; } ret = sc1200wdt_probe(); if (ret) goto out_io; ret = register_reboot_notifier(&sc1200wdt_notifier); if (ret) { printk(KERN_ERR PFX "Unable to register reboot notifier err = %d\n", ret); goto out_io; } ret = misc_register(&sc1200wdt_miscdev); if (ret) { printk(KERN_ERR PFX "Unable to register miscdev on minor %d\n", WATCHDOG_MINOR); goto out_rbt; } /* ret = 0 */ out_clean: return ret; out_rbt: unregister_reboot_notifier(&sc1200wdt_notifier); out_io: release_region(io, io_len); out_pnp: #if defined CONFIG_PNP if (isapnp) pnp_unregister_driver(&scl200wdt_pnp_driver); #endif goto out_clean; }
static int ali_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { void __user *argp = (void __user *)arg; int __user *p = argp; static struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, .firmware_version = 0, .identity = "ALi M1535 WatchDog Timer", }; switch (cmd) { case WDIOC_GETSUPPORT: return copy_to_user(argp, &ident, sizeof (ident)) ? -EFAULT : 0; case WDIOC_GETSTATUS: case WDIOC_GETBOOTSTATUS: return put_user(0, p); case WDIOC_KEEPALIVE: ali_keepalive(); return 0; case WDIOC_SETOPTIONS: { int new_options, retval = -EINVAL; if (get_user (new_options, p)) return -EFAULT; if (new_options & WDIOS_DISABLECARD) { ali_stop(); retval = 0; } if (new_options & WDIOS_ENABLECARD) { ali_start(); retval = 0; } return retval; } case WDIOC_SETTIMEOUT: { int new_timeout; if (get_user(new_timeout, p)) return -EFAULT; if (ali_settimer(new_timeout)) return -EINVAL; ali_keepalive(); /* Fall */ } case WDIOC_GETTIMEOUT: return put_user(timeout, p); default: return -ENOIOCTLCMD; } } /* * ali_open - handle open of ali watchdog * @inode: inode from VFS * @file: file from VFS * * Open the ALi watchdog device. Ensure only one person opens it * at a time. Also start the watchdog running. */ static int ali_open(struct inode *inode, struct file *file) { /* /dev/watchdog can only be opened once */ if (test_and_set_bit(0, &ali_is_open)) return -EBUSY; /* Activate */ ali_start(); return nonseekable_open(inode, file); } /* * ali_release - close an ALi watchdog * @inode: inode from VFS * @file: file from VFS * * Close the ALi watchdog device. Actual shutdown of the timer * only occurs if the magic sequence has been set. */ static int ali_release(struct inode *inode, struct file *file) { /* * Shut off the timer. */ if (ali_expect_release == 42) { ali_stop(); } else { printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); ali_keepalive(); } clear_bit(0, &ali_is_open); ali_expect_release = 0; return 0; } /* * ali_notify_sys - System down notifier * * Notifier for system down */ static int ali_notify_sys(struct notifier_block *this, unsigned long code, void *unused) { if (code==SYS_DOWN || code==SYS_HALT) { /* Turn the WDT off */ ali_stop(); } return NOTIFY_DONE; } /* * Data for PCI driver interface * * This data only exists for exporting the supported * PCI ids via MODULE_DEVICE_TABLE. We do not actually * register a pci_driver, because someone else might one day * want to register another driver on the same PCI id. */ static struct pci_device_id ali_pci_tbl[] = { { PCI_VENDOR_ID_AL, 0x1535, PCI_ANY_ID, PCI_ANY_ID,}, { 0, }, }; MODULE_DEVICE_TABLE(pci, ali_pci_tbl); /* * ali_find_watchdog - find a 1535 and 7101 * * Scans the PCI hardware for a 1535 series bridge and matching 7101 * watchdog device. This may be overtight but it is better to be safe */ static int __init ali_find_watchdog(void) { struct pci_dev *pdev; u32 wdog; /* Check for a 1535 series bridge */ pdev = pci_find_device(PCI_VENDOR_ID_AL, 0x1535, NULL); if(pdev == NULL) return -ENODEV; /* Check for the a 7101 PMU */ pdev = pci_find_device(PCI_VENDOR_ID_AL, 0x7101, NULL); if(pdev == NULL) return -ENODEV; if(pci_enable_device(pdev)) return -EIO; ali_pci = pdev; /* * Initialize the timer bits */ pci_read_config_dword(pdev, 0xCC, &wdog); wdog &= ~0x3F; /* Timer bits */ wdog &= ~((1<<27)|(1<<26)|(1<<25)|(1<<24)); /* Issued events */ wdog &= ~((1<<16)|(1<<13)|(1<<12)|(1<<11)|(1<<10)|(1<<9)); /* No monitor bits */ pci_write_config_dword(pdev, 0xCC, wdog); return 0; } /* * Kernel Interfaces */ static const struct file_operations ali_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .write = ali_write, .ioctl = ali_ioctl, .open = ali_open, .release = ali_release, }; static struct miscdevice ali_miscdev = { .minor = WATCHDOG_MINOR, .name = "watchdog", .fops = &ali_fops, }; static struct notifier_block ali_notifier = { .notifier_call = ali_notify_sys, }; /* * watchdog_init - module initialiser * * Scan for a suitable watchdog and if so initialize it. Return an error * if we cannot, the error causes the module to unload */ static int __init watchdog_init(void) { int ret; spin_lock_init(&ali_lock); /* Check whether or not the hardware watchdog is there */ if (ali_find_watchdog() != 0) { return -ENODEV; } /* Check that the timeout value is within it's range ; if not reset to the default */ if (timeout < 1 || timeout >= 18000) { timeout = WATCHDOG_TIMEOUT; printk(KERN_INFO PFX "timeout value must be 0<timeout<18000, using %d\n", timeout); } /* Calculate the watchdog's timeout */ ali_settimer(timeout); ret = misc_register(&ali_miscdev); if (ret != 0) { printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", WATCHDOG_MINOR, ret); goto out; } ret = register_reboot_notifier(&ali_notifier); if (ret != 0) { printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", ret); goto unreg_miscdev; } printk(KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d)\n", timeout, nowayout); out: return ret; unreg_miscdev: misc_deregister(&ali_miscdev); goto out; } /* * watchdog_exit - module de-initialiser * * Called while unloading a successfully installed watchdog module. */ static void __exit watchdog_exit(void) { /* Stop the timer before we leave */ ali_stop(); /* Deregister */ unregister_reboot_notifier(&ali_notifier); misc_deregister(&ali_miscdev); }
static long wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { void __user *argp = (void __user *)arg; int __user *p = argp; int new_timeout; static const struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, .firmware_version = 1, .identity = "W83697HF WDT", }; switch (cmd) { case WDIOC_GETSUPPORT: if (copy_to_user(argp, &ident, sizeof(ident))) return -EFAULT; break; case WDIOC_GETSTATUS: case WDIOC_GETBOOTSTATUS: return put_user(0, p); case WDIOC_SETOPTIONS: { int options, retval = -EINVAL; if (get_user(options, p)) return -EFAULT; if (options & WDIOS_DISABLECARD) { wdt_disable(); retval = 0; } if (options & WDIOS_ENABLECARD) { wdt_enable(); retval = 0; } return retval; } case WDIOC_KEEPALIVE: wdt_ping(); break; case WDIOC_SETTIMEOUT: if (get_user(new_timeout, p)) return -EFAULT; if (wdt_set_heartbeat(new_timeout)) return -EINVAL; wdt_ping(); case WDIOC_GETTIMEOUT: return put_user(timeout, p); default: return -ENOTTY; } return 0; } static int wdt_open(struct inode *inode, struct file *file) { if (test_and_set_bit(0, &wdt_is_open)) return -EBUSY; wdt_enable(); return nonseekable_open(inode, file); } static int wdt_close(struct inode *inode, struct file *file) { if (expect_close == 42) wdt_disable(); else { pr_crit("Unexpected close, not stopping watchdog!\n"); wdt_ping(); } expect_close = 0; clear_bit(0, &wdt_is_open); return 0; } static int wdt_notify_sys(struct notifier_block *this, unsigned long code, void *unused) { if (code == SYS_DOWN || code == SYS_HALT) wdt_disable(); return NOTIFY_DONE; } static const struct file_operations wdt_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .write = wdt_write, .unlocked_ioctl = wdt_ioctl, .open = wdt_open, .release = wdt_close, }; static struct miscdevice wdt_miscdev = { .minor = WATCHDOG_MINOR, .name = "watchdog", .fops = &wdt_fops, }; static struct notifier_block wdt_notifier = { .notifier_call = wdt_notify_sys, }; static int w83697hf_check_wdt(void) { if (!request_region(wdt_io, 2, WATCHDOG_NAME)) { pr_err("I/O address 0x%x already in use\n", wdt_io); return -EIO; } pr_debug("Looking for watchdog at address 0x%x\n", wdt_io); w83697hf_unlock(); if (w83697hf_get_reg(0x20) == 0x60) { pr_info("watchdog found at address 0x%x\n", wdt_io); w83697hf_lock(); return 0; } w83697hf_lock(); pr_info("watchdog not found at address 0x%x\n", wdt_io); release_region(wdt_io, 2); return -EIO; } static int w83697hf_ioports[] = { 0x2e, 0x4e, 0x00 }; static int __init wdt_init(void) { int ret, i, found = 0; pr_info("WDT driver for W83697HF/HG initializing\n"); if (wdt_io == 0) { for (i = 0; ((!found) && (w83697hf_ioports[i] != 0)); i++) { wdt_io = w83697hf_ioports[i]; if (!w83697hf_check_wdt()) found++; } } else { if (!w83697hf_check_wdt()) found++; } if (!found) { pr_err("No W83697HF/HG could be found\n"); ret = -EIO; goto out; } w83697hf_init(); if (early_disable) { if (wdt_running()) pr_warn("Stopping previously enabled watchdog until userland kicks in\n"); wdt_disable(); } if (wdt_set_heartbeat(timeout)) { wdt_set_heartbeat(WATCHDOG_TIMEOUT); pr_info("timeout value must be 1 <= timeout <= 255, using %d\n", WATCHDOG_TIMEOUT); } ret = register_reboot_notifier(&wdt_notifier); if (ret != 0) { pr_err("cannot register reboot notifier (err=%d)\n", ret); goto unreg_regions; } ret = misc_register(&wdt_miscdev); if (ret != 0) { pr_err("cannot register miscdev on minor=%d (err=%d)\n", WATCHDOG_MINOR, ret); goto unreg_reboot; } pr_info("initialized. timeout=%d sec (nowayout=%d)\n", timeout, nowayout); out: return ret; unreg_reboot: unregister_reboot_notifier(&wdt_notifier); unreg_regions: release_region(wdt_io, 2); goto out; } static void __exit wdt_exit(void) { misc_deregister(&wdt_miscdev); unregister_reboot_notifier(&wdt_notifier); release_region(wdt_io, 2); }
static int __init nvdumper_init(void) { int ret, dirty; #ifdef CONFIG_TEGRA_USE_NCT union nct_item_type *item; #endif if (!nvdumper_reserved) { pr_info("nvdumper: not configured\n"); return -ENOTSUPP; } nvdumper_ptr = ioremap_nocache(nvdumper_reserved, NVDUMPER_RESERVED_SIZE); if (!nvdumper_ptr) { pr_info("nvdumper: failed to ioremap memory at 0x%08lx\n", nvdumper_reserved); return -EIO; } ret = register_reboot_notifier(&nvdumper_reboot_notifier); if (ret) goto err_out1; ret = nvdumper_regdump_init(); if (ret) goto err_out2; nvdumper_dbg_footprint_init(); dirty = get_dirty_state(); switch (dirty) { case 0: pr_info("nvdumper: last reboot was clean\n"); break; case 1: pr_info("nvdumper: last reboot was dirty\n"); break; default: pr_info("nvdumper: last reboot was unknown\n"); break; } #ifdef CONFIG_TEGRA_USE_NCT item = kzalloc(sizeof(*item), GFP_KERNEL); if (!item) { pr_err("failed to allocate memory\n"); goto err_out3; } ret = tegra_nct_read_item(NCT_ID_RAMDUMP, item); if (ret < 0) { pr_err("%s: NCT read failure\n", __func__); kfree(item); goto err_out3; } pr_info("%s: RAMDUMP flag(%d) from NCT\n", __func__, item->ramdump.flag); if (item->ramdump.flag == 1) set_dirty_state(1); else set_dirty_state(0); kfree(item); return 0; err_out3: #else set_dirty_state(1); return 0; #endif err_out2: unregister_reboot_notifier(&nvdumper_reboot_notifier); err_out1: iounmap(nvdumper_ptr); return ret; }
static int eurwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { void __user *argp = (void __user *)arg; int __user *p = argp; static struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, .firmware_version = 1, .identity = "WDT Eurotech CPU-1220/1410", }; int time; int options, retval = -EINVAL; switch(cmd) { default: return -ENOTTY; case WDIOC_GETSUPPORT: return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; case WDIOC_GETSTATUS: case WDIOC_GETBOOTSTATUS: return put_user(0, p); case WDIOC_KEEPALIVE: eurwdt_ping(); return 0; case WDIOC_SETTIMEOUT: if (copy_from_user(&time, p, sizeof(int))) return -EFAULT; /* Sanity check */ if (time < 0 || time > 255) return -EINVAL; eurwdt_timeout = time; eurwdt_set_timeout(time); /* Fall */ case WDIOC_GETTIMEOUT: return put_user(eurwdt_timeout, p); case WDIOC_SETOPTIONS: if (get_user(options, p)) return -EFAULT; if (options & WDIOS_DISABLECARD) { eurwdt_disable_timer(); retval = 0; } if (options & WDIOS_ENABLECARD) { eurwdt_activate_timer(); eurwdt_ping(); retval = 0; } return retval; } } /** * eurwdt_open: * @inode: inode of device * @file: file handle to device * * The misc device has been opened. The watchdog device is single * open and on opening we load the counter. */ static int eurwdt_open(struct inode *inode, struct file *file) { if (test_and_set_bit(0, &eurwdt_is_open)) return -EBUSY; eurwdt_timeout = WDT_TIMEOUT; /* initial timeout */ /* Activate the WDT */ eurwdt_activate_timer(); return nonseekable_open(inode, file); } /** * eurwdt_release: * @inode: inode to board * @file: file handle to board * * The watchdog has a configurable API. There is a religious dispute * between people who want their watchdog to be able to shut down and * those who want to be sure if the watchdog manager dies the machine * reboots. In the former case we disable the counters, in the latter * case you have to open it again very soon. */ static int eurwdt_release(struct inode *inode, struct file *file) { if (eur_expect_close == 42) { eurwdt_disable_timer(); } else { printk(KERN_CRIT "eurwdt: Unexpected close, not stopping watchdog!\n"); eurwdt_ping(); } clear_bit(0, &eurwdt_is_open); eur_expect_close = 0; return 0; } /** * eurwdt_notify_sys: * @this: our notifier block * @code: the event being reported * @unused: unused * * Our notifier is called on system shutdowns. We want to turn the card * off at reboot otherwise the machine will reboot again during memory * test or worse yet during the following fsck. This would suck, in fact * trust me - if it happens it does suck. */ static int eurwdt_notify_sys(struct notifier_block *this, unsigned long code, void *unused) { if (code == SYS_DOWN || code == SYS_HALT) { /* Turn the card off */ eurwdt_disable_timer(); } return NOTIFY_DONE; } /* * Kernel Interfaces */ static const struct file_operations eurwdt_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .write = eurwdt_write, .ioctl = eurwdt_ioctl, .open = eurwdt_open, .release = eurwdt_release, }; static struct miscdevice eurwdt_miscdev = { .minor = WATCHDOG_MINOR, .name = "watchdog", .fops = &eurwdt_fops, }; /* * The WDT card needs to learn about soft shutdowns in order to * turn the timebomb registers off. */ static struct notifier_block eurwdt_notifier = { .notifier_call = eurwdt_notify_sys, }; /** * cleanup_module: * * Unload the watchdog. You cannot do this with any file handles open. * If your watchdog is set to continue ticking on close and you unload * it, well it keeps ticking. We won't get the interrupt but the board * will not touch PC memory so all is fine. You just have to load a new * module in 60 seconds or reboot. */ static void __exit eurwdt_exit(void) { eurwdt_lock_chip(); misc_deregister(&eurwdt_miscdev); unregister_reboot_notifier(&eurwdt_notifier); release_region(io, 2); free_irq(irq, NULL); } /** * eurwdt_init: * * Set up the WDT watchdog board. After grabbing the resources * we require we need also to unlock the device. * The open() function will actually kick the board off. */ static int __init eurwdt_init(void) { int ret; ret = misc_register(&eurwdt_miscdev); if (ret) { printk(KERN_ERR "eurwdt: can't misc_register on minor=%d\n", WATCHDOG_MINOR); goto out; } ret = request_irq(irq, eurwdt_interrupt, IRQF_DISABLED, "eurwdt", NULL); if(ret) { printk(KERN_ERR "eurwdt: IRQ %d is not free.\n", irq); goto outmisc; } if (!request_region(io, 2, "eurwdt")) { printk(KERN_ERR "eurwdt: IO %X is not free.\n", io); ret = -EBUSY; goto outirq; } ret = register_reboot_notifier(&eurwdt_notifier); if (ret) { printk(KERN_ERR "eurwdt: can't register reboot notifier (err=%d)\n", ret); goto outreg; } eurwdt_unlock_chip(); ret = 0; printk(KERN_INFO "Eurotech WDT driver 0.01 at %X (Interrupt %d)" " - timeout event: %s\n", io, irq, (!strcmp("int", ev) ? "int" : "reboot")); out: return ret; outreg: release_region(io, 2); outirq: free_irq(irq, NULL); outmisc: misc_deregister(&eurwdt_miscdev); goto out; }
static int gpio_wdt_probe(struct platform_device *pdev) { struct gpio_wdt_priv *priv; enum of_gpio_flags flags; unsigned int hw_margin; unsigned long f = 0; const char *algo; int ret; priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; priv->gpio = of_get_gpio_flags(pdev->dev.of_node, 0, &flags); if (!gpio_is_valid(priv->gpio)) return priv->gpio; priv->active_low = flags & OF_GPIO_ACTIVE_LOW; ret = of_property_read_string(pdev->dev.of_node, "hw_algo", &algo); if (ret) return ret; if (!strncmp(algo, "toggle", 6)) { priv->hw_algo = HW_ALGO_TOGGLE; f = GPIOF_IN; } else if (!strncmp(algo, "level", 5)) { priv->hw_algo = HW_ALGO_LEVEL; f = priv->active_low ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW; } else { return -EINVAL; } ret = devm_gpio_request_one(&pdev->dev, priv->gpio, f, dev_name(&pdev->dev)); if (ret) return ret; ret = of_property_read_u32(pdev->dev.of_node, "hw_margin_ms", &hw_margin); if (ret) return ret; /* Disallow values lower than 2 and higher than 65535 ms */ if (hw_margin < 2 || hw_margin > 65535) return -EINVAL; /* Use safe value (1/2 of real timeout) */ priv->hw_margin = msecs_to_jiffies(hw_margin / 2); watchdog_set_drvdata(&priv->wdd, priv); priv->wdd.info = &gpio_wdt_ident; priv->wdd.ops = &gpio_wdt_ops; priv->wdd.min_timeout = SOFT_TIMEOUT_MIN; priv->wdd.max_timeout = SOFT_TIMEOUT_MAX; if (watchdog_init_timeout(&priv->wdd, 0, &pdev->dev) < 0) priv->wdd.timeout = SOFT_TIMEOUT_DEF; setup_timer(&priv->timer, gpio_wdt_hwping, (unsigned long)&priv->wdd); ret = watchdog_register_device(&priv->wdd); if (ret) return ret; priv->notifier.notifier_call = gpio_wdt_notify_sys; ret = register_reboot_notifier(&priv->notifier); if (ret) watchdog_unregister_device(&priv->wdd); return ret; }
/* Init routine */ int __init bcm_reset_utils_init(void) { register_reboot_notifier(&reboot_notifier); return 0; }
static long ali_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { void __user *argp = (void __user *)arg; int __user *p = argp; static struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, .firmware_version = 0, .identity = "ALi M1535 WatchDog Timer", }; switch (cmd) { case WDIOC_GETSUPPORT: return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; case WDIOC_GETSTATUS: case WDIOC_GETBOOTSTATUS: return put_user(0, p); case WDIOC_SETOPTIONS: { int new_options, retval = -EINVAL; if (get_user(new_options, p)) return -EFAULT; if (new_options & WDIOS_DISABLECARD) { ali_stop(); retval = 0; } if (new_options & WDIOS_ENABLECARD) { ali_start(); retval = 0; } return retval; } case WDIOC_KEEPALIVE: ali_keepalive(); return 0; case WDIOC_SETTIMEOUT: { int new_timeout; if (get_user(new_timeout, p)) return -EFAULT; if (ali_settimer(new_timeout)) return -EINVAL; ali_keepalive(); } case WDIOC_GETTIMEOUT: return put_user(timeout, p); default: return -ENOTTY; } } static int ali_open(struct inode *inode, struct file *file) { if (test_and_set_bit(0, &ali_is_open)) return -EBUSY; ali_start(); return nonseekable_open(inode, file); } static int ali_release(struct inode *inode, struct file *file) { if (ali_expect_release == 42) ali_stop(); else { printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); ali_keepalive(); } clear_bit(0, &ali_is_open); ali_expect_release = 0; return 0; } static int ali_notify_sys(struct notifier_block *this, unsigned long code, void *unused) { if (code == SYS_DOWN || code == SYS_HALT) ali_stop(); return NOTIFY_DONE; } static struct pci_device_id ali_pci_tbl[] = { { PCI_VENDOR_ID_AL, 0x1533, PCI_ANY_ID, PCI_ANY_ID,}, { PCI_VENDOR_ID_AL, 0x1535, PCI_ANY_ID, PCI_ANY_ID,}, { 0, }, }; MODULE_DEVICE_TABLE(pci, ali_pci_tbl); static int __init ali_find_watchdog(void) { struct pci_dev *pdev; u32 wdog; pdev = pci_get_device(PCI_VENDOR_ID_AL, 0x1535, NULL); if (pdev == NULL) pdev = pci_get_device(PCI_VENDOR_ID_AL, 0x1533, NULL); if (pdev == NULL) return -ENODEV; pci_dev_put(pdev); pdev = pci_get_device(PCI_VENDOR_ID_AL, 0x7101, NULL); if (pdev == NULL) return -ENODEV; if (pci_enable_device(pdev)) { pci_dev_put(pdev); return -EIO; } ali_pci = pdev; pci_read_config_dword(pdev, 0xCC, &wdog); wdog &= ~0x3F; wdog &= ~((1 << 27)|(1 << 26)|(1 << 25)|(1 << 24)); wdog &= ~((1 << 16)|(1 << 13)|(1 << 12)|(1 << 11)|(1 << 10)|(1 << 9)); pci_write_config_dword(pdev, 0xCC, wdog); return 0; } static const struct file_operations ali_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .write = ali_write, .unlocked_ioctl = ali_ioctl, .open = ali_open, .release = ali_release, }; static struct miscdevice ali_miscdev = { .minor = WATCHDOG_MINOR, .name = "watchdog", .fops = &ali_fops, }; static struct notifier_block ali_notifier = { .notifier_call = ali_notify_sys, }; static int __init watchdog_init(void) { int ret; if (ali_find_watchdog() != 0) return -ENODEV; if (timeout < 1 || timeout >= 18000) { timeout = WATCHDOG_TIMEOUT; printk(KERN_INFO PFX "timeout value must be 0 < timeout < 18000, using %d\n", timeout); } ali_settimer(timeout); ret = register_reboot_notifier(&ali_notifier); if (ret != 0) { printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", ret); goto out; } ret = misc_register(&ali_miscdev); if (ret != 0) { printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", WATCHDOG_MINOR, ret); goto unreg_reboot; } printk(KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d)\n", timeout, nowayout); out: return ret; unreg_reboot: unregister_reboot_notifier(&ali_notifier); goto out; } static void __exit watchdog_exit(void) { ali_stop(); misc_deregister(&ali_miscdev); unregister_reboot_notifier(&ali_notifier); pci_dev_put(ali_pci); }
int __init xpc_init(void) { int ret; short partid; struct xpc_partition *part; struct task_struct *kthread; size_t buf_size; if (!ia64_platform_is("sn2")) return -ENODEV; buf_size = max(XPC_RP_VARS_SIZE, XPC_RP_HEADER_SIZE + XP_NASID_MASK_BYTES); xpc_remote_copy_buffer = xpc_kmalloc_cacheline_aligned(buf_size, GFP_KERNEL, &xpc_remote_copy_buffer_base); if (xpc_remote_copy_buffer == NULL) return -ENOMEM; snprintf(xpc_part->bus_id, BUS_ID_SIZE, "part"); snprintf(xpc_chan->bus_id, BUS_ID_SIZE, "chan"); xpc_sysctl = register_sysctl_table(xpc_sys_dir); /* * The first few fields of each entry of xpc_partitions[] need to * be initialized now so that calls to xpc_connect() and * xpc_disconnect() can be made prior to the activation of any remote * partition. NOTE THAT NONE OF THE OTHER FIELDS BELONGING TO THESE * ENTRIES ARE MEANINGFUL UNTIL AFTER AN ENTRY'S CORRESPONDING * PARTITION HAS BEEN ACTIVATED. */ for (partid = 1; partid < XP_MAX_PARTITIONS; partid++) { part = &xpc_partitions[partid]; DBUG_ON((u64)part != L1_CACHE_ALIGN((u64)part)); part->act_IRQ_rcvd = 0; spin_lock_init(&part->act_lock); part->act_state = XPC_P_INACTIVE; XPC_SET_REASON(part, 0, 0); init_timer(&part->disengage_request_timer); part->disengage_request_timer.function = xpc_timeout_partition_disengage_request; part->disengage_request_timer.data = (unsigned long)part; part->setup_state = XPC_P_UNSET; init_waitqueue_head(&part->teardown_wq); atomic_set(&part->references, 0); } /* * Open up protections for IPI operations (and AMO operations on * Shub 1.1 systems). */ xpc_allow_IPI_ops(); /* * Interrupts being processed will increment this atomic variable and * awaken the heartbeat thread which will process the interrupts. */ atomic_set(&xpc_act_IRQ_rcvd, 0); /* * This is safe to do before the xpc_hb_checker thread has started * because the handler releases a wait queue. If an interrupt is * received before the thread is waiting, it will not go to sleep, * but rather immediately process the interrupt. */ ret = request_irq(SGI_XPC_ACTIVATE, xpc_act_IRQ_handler, 0, "xpc hb", NULL); if (ret != 0) { dev_err(xpc_part, "can't register ACTIVATE IRQ handler, " "errno=%d\n", -ret); xpc_restrict_IPI_ops(); if (xpc_sysctl) unregister_sysctl_table(xpc_sysctl); kfree(xpc_remote_copy_buffer_base); return -EBUSY; } /* * Fill the partition reserved page with the information needed by * other partitions to discover we are alive and establish initial * communications. */ xpc_rsvd_page = xpc_rsvd_page_init(); if (xpc_rsvd_page == NULL) { dev_err(xpc_part, "could not setup our reserved page\n"); free_irq(SGI_XPC_ACTIVATE, NULL); xpc_restrict_IPI_ops(); if (xpc_sysctl) unregister_sysctl_table(xpc_sysctl); kfree(xpc_remote_copy_buffer_base); return -EBUSY; } /* add ourselves to the reboot_notifier_list */ ret = register_reboot_notifier(&xpc_reboot_notifier); if (ret != 0) dev_warn(xpc_part, "can't register reboot notifier\n"); /* add ourselves to the die_notifier list */ ret = register_die_notifier(&xpc_die_notifier); if (ret != 0) dev_warn(xpc_part, "can't register die notifier\n"); init_timer(&xpc_hb_timer); xpc_hb_timer.function = xpc_hb_beater; /* * The real work-horse behind xpc. This processes incoming * interrupts and monitors remote heartbeats. */ kthread = kthread_run(xpc_hb_checker, NULL, XPC_HB_CHECK_THREAD_NAME); if (IS_ERR(kthread)) { dev_err(xpc_part, "failed while forking hb check thread\n"); /* indicate to others that our reserved page is uninitialized */ xpc_rsvd_page->vars_pa = 0; /* take ourselves off of the reboot_notifier_list */ (void)unregister_reboot_notifier(&xpc_reboot_notifier); /* take ourselves off of the die_notifier list */ (void)unregister_die_notifier(&xpc_die_notifier); del_timer_sync(&xpc_hb_timer); free_irq(SGI_XPC_ACTIVATE, NULL); xpc_restrict_IPI_ops(); if (xpc_sysctl) unregister_sysctl_table(xpc_sysctl); kfree(xpc_remote_copy_buffer_base); return -EBUSY; } /* * Startup a thread that will attempt to discover other partitions to * activate based on info provided by SAL. This new thread is short * lived and will exit once discovery is complete. */ kthread = kthread_run(xpc_initiate_discovery, NULL, XPC_DISCOVERY_THREAD_NAME); if (IS_ERR(kthread)) { dev_err(xpc_part, "failed while forking discovery thread\n"); /* mark this new thread as a non-starter */ complete(&xpc_discovery_exited); xpc_do_exit(xpUnloading); return -EBUSY; } /* set the interface to point at XPC's functions */ xpc_set_interface(xpc_initiate_connect, xpc_initiate_disconnect, xpc_initiate_allocate, xpc_initiate_send, xpc_initiate_send_notify, xpc_initiate_received, xpc_initiate_partid_to_nasids); return 0; }
static int pn544_probe(struct i2c_client *client, const struct i2c_device_id *id) { int ret = -ENODEV; struct pn544_i2c_platform_data *platform_data; struct pn544_dev *pn544_dev; pr_debug("%s : Probing pn544 driver\n", __func__); if (client->dev.of_node) platform_data = pn544_of_init(client); else platform_data = client->dev.platform_data; if (!platform_data) { pr_err("%s : GPIO has value 0, nfc probe fail.\n", __func__); goto err_exit; } if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { pr_err("%s : i2c_check_functionality I2C_FUNC_I2C failed.\n", __func__); goto err_exit; } pn544_dev = kzalloc(sizeof(*pn544_dev), GFP_KERNEL); if (pn544_dev == NULL) { dev_err(&client->dev, "failed to allocate memory for module data\n"); ret = -ENOMEM; goto err_exit; } ret = pn544_gpio_init(platform_data); if (ret) { dev_err(&client->dev, "gpio init failed\n"); goto err_gpio_init; } pn544_dev->irq_gpio = platform_data->irq_gpio; pn544_dev->ven_gpio = platform_data->ven_gpio; pn544_dev->firmware_gpio = platform_data->firmware_gpio; pn544_dev->ven_polarity = platform_data->ven_polarity; pn544_dev->discharge_delay = platform_data->discharge_delay; pn544_dev->client = client; wake_lock_init(&pn544_dev->wakelock, WAKE_LOCK_SUSPEND, "pn544c3"); /* init mutex and queues */ init_waitqueue_head(&pn544_dev->read_wq); mutex_init(&pn544_dev->read_mutex); mutex_init(&pn544_dev->ioctl_mutex); spin_lock_init(&pn544_dev->irq_enabled_lock); pn544_dev->pn544_device.minor = MISC_DYNAMIC_MINOR; pn544_dev->pn544_device.name = "pn544"; pn544_dev->pn544_device.fops = &pn544_dev_fops; ret = misc_register(&pn544_dev->pn544_device); if (ret) { pr_err("%s : misc_register failed.\n", __FILE__); goto err_misc_register; } pr_debug("%s : PN544 Misc Minor: %d\n", __func__, pn544_dev->pn544_device.minor); /* Get the device structure */ pn544_dev->pn544_control_device = pn544_dev->pn544_device.this_device; /* Create sysfs device for PN544 control functionality */ ret = device_create_file(pn544_dev->pn544_control_device, &dev_attr_pn544_control_dev); if (ret) { pr_err("%s : device_create_file failed\n", __FILE__); goto err_device_create_file_failed; } /* request irq. the irq is set whenever the chip has data available * for reading. it is cleared when all data has been read. */ pr_debug("%s : requesting IRQ %d\n", __func__, client->irq); pn544_dev->irq_enabled = true; ret = request_irq(client->irq, pn544_dev_irq_handler, IRQF_TRIGGER_HIGH, client->name, pn544_dev); if (ret) { dev_err(&client->dev, "request_irq failed\n"); goto err_request_irq_failed; } if (unlikely(irq_set_irq_wake(client->irq, 1))) pr_err("%s : unable to make irq %d wakeup\n", __func__, client->irq); pn544_disable_irq(pn544_dev); pn544_dev->reboot_notify.notifier_call = nfc_blk_reboot_notify; register_reboot_notifier(&pn544_dev->reboot_notify); i2c_set_clientdata(client, pn544_dev); return 0; err_request_irq_failed: device_remove_file(pn544_dev->pn544_control_device, &dev_attr_pn544_control_dev); err_device_create_file_failed: misc_deregister(&pn544_dev->pn544_device); err_misc_register: mutex_destroy(&pn544_dev->ioctl_mutex); mutex_destroy(&pn544_dev->read_mutex); pn544_gpio_free(pn544_dev); wake_unlock(&pn544_dev->wakelock); wake_lock_destroy(&pn544_dev->wakelock); err_gpio_init: kfree(pn544_dev); err_exit: return ret; }
static long indydog_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { int options, retval = -EINVAL; static struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, .firmware_version = 0, .identity = "Hardware Watchdog for SGI IP22", }; switch (cmd) { case WDIOC_GETSUPPORT: if (copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))) return -EFAULT; return 0; case WDIOC_GETSTATUS: case WDIOC_GETBOOTSTATUS: return put_user(0, (int *)arg); case WDIOC_SETOPTIONS: { if (get_user(options, (int *)arg)) return -EFAULT; if (options & WDIOS_DISABLECARD) { indydog_stop(); retval = 0; } if (options & WDIOS_ENABLECARD) { indydog_start(); retval = 0; } return retval; } case WDIOC_KEEPALIVE: indydog_ping(); return 0; case WDIOC_GETTIMEOUT: return put_user(WATCHDOG_TIMEOUT, (int *)arg); default: return -ENOTTY; } } static int indydog_notify_sys(struct notifier_block *this, unsigned long code, void *unused) { if (code == SYS_DOWN || code == SYS_HALT) indydog_stop(); /* Turn the WDT off */ return NOTIFY_DONE; } static const struct file_operations indydog_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .write = indydog_write, .unlocked_ioctl = indydog_ioctl, .open = indydog_open, .release = indydog_release, }; static struct miscdevice indydog_miscdev = { .minor = WATCHDOG_MINOR, .name = "watchdog", .fops = &indydog_fops, }; static struct notifier_block indydog_notifier = { .notifier_call = indydog_notify_sys, }; static char banner[] __initdata = KERN_INFO PFX "Hardware Watchdog Timer for SGI IP22: 0.3\n"; static int __init watchdog_init(void) { int ret; spin_lock_init(&indydog_lock); ret = register_reboot_notifier(&indydog_notifier); if (ret) { printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", ret); return ret; } ret = misc_register(&indydog_miscdev); if (ret) { printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", WATCHDOG_MINOR, ret); unregister_reboot_notifier(&indydog_notifier); return ret; } printk(banner); return 0; } static void __exit watchdog_exit(void) { misc_deregister(&indydog_miscdev); unregister_reboot_notifier(&indydog_notifier); }
static int hif_usb_probe(struct usb_interface *interface, const struct usb_device_id *id) { int ret = 0; struct hif_usb_softc *sc; struct ol_softc *ol_sc; struct usb_device *pdev = interface_to_usbdev(interface); int vendor_id, product_id; pr_info("hif_usb_probe\n"); usb_get_dev(pdev); vendor_id = le16_to_cpu(pdev->descriptor.idVendor); product_id = le16_to_cpu(pdev->descriptor.idProduct); ret = 0; sc = A_MALLOC(sizeof(*sc)); if (!sc) { ret = -ENOMEM; goto err_alloc; } OS_MEMZERO(sc, sizeof(*sc)); sc->pdev = (void *)pdev; sc->dev = &pdev->dev; sc->aps_osdev.bdev = pdev; sc->aps_osdev.device = &pdev->dev; sc->aps_osdev.bc.bc_bustype = HAL_BUS_TYPE_AHB; sc->devid = id->idProduct; adf_os_spinlock_init(&sc->target_lock); ol_sc = A_MALLOC(sizeof(*ol_sc)); if (!ol_sc) goto err_attach; OS_MEMZERO(ol_sc, sizeof(*ol_sc)); ol_sc->sc_osdev = &sc->aps_osdev; ol_sc->hif_sc = (void *)sc; sc->ol_sc = ol_sc; if ((usb_control_msg(pdev, usb_sndctrlpipe(pdev, 0), USB_REQ_SET_CONFIGURATION, 0, 1, 0, NULL, 0, HZ)) < 0) { pr_info("%s[%d]\n\r", __func__, __LINE__); } usb_set_interface(pdev, 0, 0); if (hif_usb_configure(sc, &ol_sc->hif_hdl, interface)) goto err_config; ol_sc->enableuartprint = 1; ol_sc->enablefwlog = 0; ol_sc->enablesinglebinary = FALSE; ol_sc->max_no_of_peers = 1; init_waitqueue_head(&ol_sc->sc_osdev->event_queue); ret = hdd_wlan_startup(&pdev->dev, ol_sc); if (ret) { hif_nointrs(sc); if (sc->hif_device != NULL) { ((HIF_DEVICE_USB *)(sc->hif_device))->sc = NULL; } athdiag_procfs_remove(); goto err_config; } sc->hdd_removed = 0; sc->hdd_removed_processing = 0; sc->hdd_removed_wait_cnt = 0; #ifndef REMOVE_PKT_LOG if (vos_get_conparam() != VOS_FTM_MODE && !WLAN_IS_EPPING_ENABLED(vos_get_conparam())) { /* * pktlog initialization */ ol_pl_sethandle(&ol_sc->pdev_txrx_handle->pl_dev, ol_sc); if (pktlogmod_init(ol_sc)) pr_err("%s: pktlogmod_init failed\n", __func__); } #endif #ifdef WLAN_BTAMP_FEATURE /* Send WLAN UP indication to Nlink Service */ send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0); #endif sc->interface = interface; sc->reboot_notifier.notifier_call = hif_usb_reboot; register_reboot_notifier(&sc->reboot_notifier); usb_sc = sc; return 0; err_config: A_FREE(ol_sc); err_attach: ret = -EIO; usb_sc = NULL; A_FREE(sc); err_alloc: usb_put_dev(pdev); return ret; }
static int fop_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { void __user *argp = (void __user *)arg; int __user *p = argp; static struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, .firmware_version = 1, .identity = "SC520", }; switch(cmd) { default: return -ENOIOCTLCMD; case WDIOC_GETSUPPORT: return copy_to_user(argp, &ident, sizeof(ident))?-EFAULT:0; case WDIOC_GETSTATUS: case WDIOC_GETBOOTSTATUS: return put_user(0, p); case WDIOC_KEEPALIVE: wdt_keepalive(); return 0; case WDIOC_SETOPTIONS: { int new_options, retval = -EINVAL; if(get_user(new_options, p)) return -EFAULT; if(new_options & WDIOS_DISABLECARD) { wdt_turnoff(); retval = 0; } if(new_options & WDIOS_ENABLECARD) { wdt_startup(); retval = 0; } return retval; } case WDIOC_SETTIMEOUT: { int new_timeout; if(get_user(new_timeout, p)) return -EFAULT; if(wdt_set_heartbeat(new_timeout)) return -EINVAL; wdt_keepalive(); /* Fall through */ } case WDIOC_GETTIMEOUT: return put_user(timeout, p); } } static const struct file_operations wdt_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .write = fop_write, .open = fop_open, .release = fop_close, .ioctl = fop_ioctl, }; static struct miscdevice wdt_miscdev = { .minor = WATCHDOG_MINOR, .name = "watchdog", .fops = &wdt_fops, }; /* * Notifier for system down */ static int wdt_notify_sys(struct notifier_block *this, unsigned long code, void *unused) { if(code==SYS_DOWN || code==SYS_HALT) wdt_turnoff(); return NOTIFY_DONE; } /* * The WDT needs to learn about soft shutdowns in order to * turn the timebomb registers off. */ static struct notifier_block wdt_notifier = { .notifier_call = wdt_notify_sys, }; static void __exit sc520_wdt_unload(void) { if (!nowayout) wdt_turnoff(); /* Deregister */ misc_deregister(&wdt_miscdev); unregister_reboot_notifier(&wdt_notifier); iounmap(wdtmrctl); } static int __init sc520_wdt_init(void) { int rc = -EBUSY; spin_lock_init(&wdt_spinlock); init_timer(&timer); timer.function = wdt_timer_ping; timer.data = 0; /* Check that the timeout value is within it's range ; if not reset to the default */ if (wdt_set_heartbeat(timeout)) { wdt_set_heartbeat(WATCHDOG_TIMEOUT); printk(KERN_INFO PFX "timeout value must be 1<=timeout<=3600, using %d\n", WATCHDOG_TIMEOUT); } wdtmrctl = ioremap((unsigned long)(MMCR_BASE + OFFS_WDTMRCTL), 2); if (!wdtmrctl) { printk(KERN_ERR PFX "Unable to remap memory\n"); rc = -ENOMEM; goto err_out_region2; } rc = register_reboot_notifier(&wdt_notifier); if (rc) { printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", rc); goto err_out_ioremap; } rc = misc_register(&wdt_miscdev); if (rc) { printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", WATCHDOG_MINOR, rc); goto err_out_notifier; } printk(KERN_INFO PFX "WDT driver for SC520 initialised. timeout=%d sec (nowayout=%d)\n", timeout,nowayout); return 0; err_out_notifier: unregister_reboot_notifier(&wdt_notifier); err_out_ioremap: iounmap(wdtmrctl); err_out_region2: return rc; } module_init(sc520_wdt_init); module_exit(sc520_wdt_unload); MODULE_AUTHOR("Scott and Bill Jennings"); MODULE_DESCRIPTION("Driver for watchdog timer in AMD \"Elan\" SC520 uProcessor"); MODULE_LICENSE("GPL"); MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
static long wdog_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { void __user *argp = (void __user *)arg; int __user *p = argp; int new_heartbeat; int status; int options; uint32_t remaining; struct watchdog_info ident = { .options = WDIOF_SETTIMEOUT| WDIOF_MAGICCLOSE| WDIOF_KEEPALIVEPING, .firmware_version = 1, .identity = "BCM2708", }; switch (cmd) { case WDIOC_GETSUPPORT: return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; case WDIOC_GETSTATUS: status = wdog_get_status(); return put_user(status, p); case WDIOC_GETBOOTSTATUS: return put_user(0, p); case WDIOC_KEEPALIVE: wdog_ping(); return 0; case WDIOC_SETTIMEOUT: if (get_user(new_heartbeat, p)) return -EFAULT; if (wdog_set_heartbeat(new_heartbeat)) return -EINVAL; wdog_ping(); /* Fall */ case WDIOC_GETTIMEOUT: return put_user(heartbeat, p); case WDIOC_GETTIMELEFT: remaining = WDOG_TICKS_TO_SECS(wdog_get_remaining()); return put_user(remaining, p); case WDIOC_SETOPTIONS: if (get_user(options, p)) return -EFAULT; if (options & WDIOS_DISABLECARD) wdog_stop(); if (options & WDIOS_ENABLECARD) wdog_start(wdog_ticks); return 0; default: return -ENOTTY; } } /** * @inode: inode of device * @file: file handle to device * * The watchdog device has been opened. The watchdog device is single * open and on opening we load the counters. */ static int wdog_open(struct inode *inode, struct file *file) { if (test_and_set_bit(0, &wdog_is_open)) return -EBUSY; /* * Activate */ wdog_start(wdog_ticks); return nonseekable_open(inode, file); } /** * @inode: inode to board * @file: file handle to board * * The watchdog has a configurable API. There is a religious dispute * between people who want their watchdog to be able to shut down and * those who want to be sure if the watchdog manager dies the machine * reboots. In the former case we disable the counters, in the latter * case you have to open it again very soon. */ static int wdog_release(struct inode *inode, struct file *file) { if (expect_close == 42) { wdog_stop(); } else { printk(KERN_CRIT "wdt: WDT device closed unexpectedly. WDT will not stop!\n"); wdog_ping(); } clear_bit(0, &wdog_is_open); expect_close = 0; return 0; } /** * @this: our notifier block * @code: the event being reported * @unused: unused * * Our notifier is called on system shutdowns. Turn the watchdog * off so that it does not fire during the next reboot. */ static int wdog_notify_sys(struct notifier_block *this, unsigned long code, void *unused) { if (code == SYS_DOWN || code == SYS_HALT) wdog_stop(); return NOTIFY_DONE; } /* * Kernel Interfaces */ static const struct file_operations wdog_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .write = wdog_write, .unlocked_ioctl = wdog_ioctl, .open = wdog_open, .release = wdog_release, }; static struct miscdevice wdog_miscdev = { .minor = WATCHDOG_MINOR, .name = "watchdog", .fops = &wdog_fops, }; /* * The WDT card needs to learn about soft shutdowns in order to * turn the timebomb registers off. */ static struct notifier_block wdog_notifier = { .notifier_call = wdog_notify_sys, }; /** * cleanup_module: * * Unload the watchdog. You cannot do this with any file handles open. * If your watchdog is set to continue ticking on close and you unload * it, well it keeps ticking. We won't get the interrupt but the board * will not touch PC memory so all is fine. You just have to load a new * module in 60 seconds or reboot. */ static void __exit wdog_exit(void) { misc_deregister(&wdog_miscdev); unregister_reboot_notifier(&wdog_notifier); } static int __init wdog_init(void) { int ret; /* Check that the heartbeat value is within it's range; if not reset to the default */ if (wdog_set_heartbeat(heartbeat)) { wdog_set_heartbeat(WD_TIMO); printk(KERN_INFO "bcm2708_wdog: heartbeat value must be " "0 < heartbeat < %d, using %d\n", WDOG_TICKS_TO_SECS(PM_WDOG_TIME_SET), WD_TIMO); } ret = register_reboot_notifier(&wdog_notifier); if (ret) { printk(KERN_ERR "wdt: cannot register reboot notifier (err=%d)\n", ret); goto out_reboot; } ret = misc_register(&wdog_miscdev); if (ret) { printk(KERN_ERR "wdt: cannot register miscdev on minor=%d (err=%d)\n", WATCHDOG_MINOR, ret); goto out_misc; } printk(KERN_INFO "bcm2708 watchdog, heartbeat=%d sec (nowayout=%d)\n", heartbeat, nowayout); return 0; out_misc: unregister_reboot_notifier(&wdog_notifier); out_reboot: return ret; }
static long intel_scu_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { void __user *argp = (void __user *)arg; u32 __user *p = argp; u32 new_margin; static const struct watchdog_info ident = { .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, .firmware_version = 0, /* @todo Get from SCU via ipc_get_scu_fw_version()? */ .identity = "Intel_SCU IOH Watchdog" /* len < 32 */ }; switch (cmd) { case WDIOC_GETSUPPORT: return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; case WDIOC_GETSTATUS: case WDIOC_GETBOOTSTATUS: return put_user(0, p); case WDIOC_KEEPALIVE: intel_scu_keepalive(); return 0; case WDIOC_SETTIMEOUT: if (get_user(new_margin, p)) return -EFAULT; if (check_timer_margin(new_margin)) return -EINVAL; if (intel_scu_set_heartbeat(new_margin)) return -EINVAL; return 0; case WDIOC_GETTIMEOUT: return put_user(watchdog_device.soft_threshold, p); default: return -ENOTTY; } } /* * Notifier for system down */ static int intel_scu_notify_sys(struct notifier_block *this, unsigned long code, void *another_unused) { if (code == SYS_DOWN || code == SYS_HALT) /* Turn off the watchdog timer. */ intel_scu_stop(); return NOTIFY_DONE; } /* * Kernel Interfaces */ static const struct file_operations intel_scu_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .write = intel_scu_write, .unlocked_ioctl = intel_scu_ioctl, .open = intel_scu_open, .release = intel_scu_release, }; static int __init intel_scu_watchdog_init(void) { int ret; u32 __iomem *tmp_addr; /* * We don't really need to check this as the SFI timer get will fail * but if we do so we can exit with a clearer reason and no noise. * * If it isn't an intel MID device then it doesn't have this watchdog */ if (!mrst_identify_cpu()) return -ENODEV; /* Check boot parameters to verify that their initial values */ /* are in range. */ /* Check value of timer_set boot parameter */ if ((timer_set < MIN_TIME_CYCLE) || (timer_set > MAX_TIME - MIN_TIME_CYCLE)) { pr_err("Watchdog timer: value of timer_set %x (hex) " "is out of range from %x to %x (hex)\n", timer_set, MIN_TIME_CYCLE, MAX_TIME - MIN_TIME_CYCLE); return -EINVAL; } /* Check value of timer_margin boot parameter */ if (check_timer_margin(timer_margin)) return -EINVAL; watchdog_device.timer_tbl_ptr = sfi_get_mtmr(sfi_mtimer_num-1); if (watchdog_device.timer_tbl_ptr == NULL) { pr_debug("Watchdog timer - Intel SCU watchdog: timer is not available\n"); return -ENODEV; } /* make sure the timer exists */ if (watchdog_device.timer_tbl_ptr->phys_addr == 0) { pr_debug("Watchdog timer - Intel SCU watchdog - timer %d does not have valid physical memory\n", sfi_mtimer_num); return -ENODEV; } if (watchdog_device.timer_tbl_ptr->irq == 0) { pr_debug("Watchdog timer: timer %d invalid irq\n", sfi_mtimer_num); return -ENODEV; } tmp_addr = ioremap_nocache(watchdog_device.timer_tbl_ptr->phys_addr, 20); if (tmp_addr == NULL) { pr_debug("Watchdog timer: timer unable to ioremap\n"); return -ENOMEM; } watchdog_device.timer_load_count_addr = tmp_addr++; watchdog_device.timer_current_value_addr = tmp_addr++; watchdog_device.timer_control_addr = tmp_addr++; watchdog_device.timer_clear_interrupt_addr = tmp_addr++; watchdog_device.timer_interrupt_status_addr = tmp_addr++; /* Set the default time values in device structure */ watchdog_device.timer_set = timer_set; watchdog_device.threshold = timer_margin * watchdog_device.timer_tbl_ptr->freq_hz; watchdog_device.soft_threshold = (watchdog_device.timer_set - timer_margin) * watchdog_device.timer_tbl_ptr->freq_hz; watchdog_device.intel_scu_notifier.notifier_call = intel_scu_notify_sys; ret = register_reboot_notifier(&watchdog_device.intel_scu_notifier); if (ret) { pr_err("Watchdog timer: cannot register notifier %d)\n", ret); goto register_reboot_error; } watchdog_device.miscdev.minor = WATCHDOG_MINOR; watchdog_device.miscdev.name = "watchdog"; watchdog_device.miscdev.fops = &intel_scu_fops; ret = misc_register(&watchdog_device.miscdev); if (ret) { pr_err("Watchdog timer: cannot register miscdev %d err =%d\n", WATCHDOG_MINOR, ret); goto misc_register_error; } ret = request_irq((unsigned int)watchdog_device.timer_tbl_ptr->irq, watchdog_timer_interrupt, IRQF_SHARED, "watchdog", &watchdog_device.timer_load_count_addr); if (ret) { pr_err("Watchdog timer: error requesting irq %d\n", ret); goto request_irq_error; } /* Make sure timer is disabled before returning */ intel_scu_stop(); return 0; /* error cleanup */ request_irq_error: misc_deregister(&watchdog_device.miscdev); misc_register_error: unregister_reboot_notifier(&watchdog_device.intel_scu_notifier); register_reboot_error: intel_scu_stop(); iounmap(watchdog_device.timer_load_count_addr); return ret; }
/** * @Copyright (C) Anyka 2012 * @brief probe battery * @author Gao wangsheng * @email [email protected] * @date 2012-11-2 * @param[out] void * @param[in] *dev * @return fail or not */ static int __devinit ak_battery_probe(struct platform_device *dev) { int ret = 0; struct ak_bat_mach_info *info; info = (struct ak_bat_mach_info *)dev->dev.platform_data; if (!info) { printk(KERN_ERR "%s:no platform data for battery\n",__func__); ret = -EINVAL; goto nodata_out; } /* initialize hardware */ mutex_init(&bat_device.bat_lock); bat_device.rd_voltage.sample = info->bat_mach_info.voltage_sample; bat_device.rd_voltage.design_max = info->bat_mach_info.max_voltage; init_timer(&bat_device.timer); bat_device.timer.function = bat_charge_full_timer; bat_device.timer.data = (unsigned long) &bat_device; INIT_DELAYED_WORK(&charge_work,bat_charge_work); INIT_DELAYED_WORK(&discharge_work,bat_discharge_work); INIT_DELAYED_WORK(&voltage_work,bat_voltage_work); INIT_DELAYED_WORK(&usbirq_work,bat_usbirq_work); INIT_DELAYED_WORK(&pdown_work,bat_pdown_work); INIT_DELAYED_WORK(&resume_work,bat_resume_work); ret = power_supply_register(&dev->dev, &bat_device.bat_ps); if (ret != 0) { goto cancel_out; } ret = power_supply_register(&dev->dev,&bat_device.usb_ps); if (ret != 0) { goto free_bat_ps_out; } ret = power_supply_register(&dev->dev,&bat_device.ac_ps); if (ret != 0) { goto free_usb_ps_out; } // use for charge full state if (info->full_gpio.pindata.pin >= 0) { info->gpio_init(&info->full_gpio.pindata); } if (info->ac_gpio.is_detect_mode == BAT_CHARGE_GPIO_DETECT) { INIT_DELAYED_WORK(&acirq_work,bat_acirq_work); // use for ac charge in irq if (info->ac_gpio.irq >= 0) { info->gpio_init(&info->ac_gpio.pindata); bat_set_int_inverse(info->ac_gpio.pindata.pin); if (request_irq(info->ac_gpio.irq,akbat_ac_irqhandler,0,"ac_charge",&bat_device)) { printk(KERN_ERR "%s:Could not allocate IRQ %d\n", __func__,info->ac_gpio.irq); ret = -EIO; goto free_ac_ps_out; } } } else if (info->ac_gpio.is_detect_mode == BAT_CHARGE_ADC_DETECT) { memset(&ac_detect_nb, 0, sizeof(ac_detect_nb)); ac_detect_nb.notifier_call = ac_detect_plugin; addetect_register_client(&ac_detect_nb); } // use for usb charge in irq if (info->usb_gpio.irq >= 0) { info->gpio_init(&info->usb_gpio.pindata); mdelay(100); bat_set_int_inverse(info->usb_gpio.pindata.pin); if (request_irq(info->usb_gpio.irq,akbat_usb_irqhandler,0,"usb_charge",&bat_device)) { printk(KERN_ERR "%s:Could not allocate IRQ %d\n", __func__,info->usb_gpio.irq); ret = -EIO; goto free_acirq_out; } } ak_bat_update(&bat_device); schedule_delayed_work(&voltage_work,UPDATE_VOLTAGE_DELAY); register_reboot_notifier(&battery_reboot_nb); bat_print_battery_info(&bat_device); printk("AK Battery initialized\n"); return ret; free_acirq_out: if (info->ac_gpio.irq > 0) { disable_irq(info->ac_gpio.irq); free_irq(info->ac_gpio.irq, dev); } free_ac_ps_out: power_supply_unregister(&bat_device.ac_ps); free_usb_ps_out: power_supply_unregister(&bat_device.usb_ps); free_bat_ps_out: power_supply_unregister(&bat_device.bat_ps); cancel_out: del_timer_sync(&bat_device.timer); cancel_delayed_work_sync(&charge_work); cancel_delayed_work_sync(&discharge_work); cancel_delayed_work_sync(&voltage_work); cancel_delayed_work_sync(&usbirq_work); cancel_delayed_work_sync(&acirq_work); cancel_delayed_work_sync(&pdown_work); cancel_delayed_work_sync(&resume_work); nodata_out: printk(KERN_ERR "###########%s:ERR out##########\n",__func__); return ret; }
int __init xpc_init(void) { int ret; struct task_struct *kthread; dev_set_name(xpc_part, "part"); dev_set_name(xpc_chan, "chan"); if (is_shub()) { /* * The ia64-sn2 architecture supports at most 64 partitions. * And the inability to unregister remote amos restricts us * further to only support exactly 64 partitions on this * architecture, no less. */ if (xp_max_npartitions != 64) { dev_err(xpc_part, "max #of partitions not set to 64\n"); ret = -EINVAL; } else { ret = xpc_init_sn2(); } } else if (is_uv()) { ret = xpc_init_uv(); } else { ret = -ENODEV; } if (ret != 0) return ret; ret = xpc_setup_partitions(); if (ret != 0) { dev_err(xpc_part, "can't get memory for partition structure\n"); goto out_1; } xpc_sysctl = register_sysctl_table(xpc_sys_dir); /* * Fill the partition reserved page with the information needed by * other partitions to discover we are alive and establish initial * communications. */ ret = xpc_setup_rsvd_page(); if (ret != 0) { dev_err(xpc_part, "can't setup our reserved page\n"); goto out_2; } /* add ourselves to the reboot_notifier_list */ ret = register_reboot_notifier(&xpc_reboot_notifier); if (ret != 0) dev_warn(xpc_part, "can't register reboot notifier\n"); /* add ourselves to the die_notifier list */ ret = register_die_notifier(&xpc_die_notifier); if (ret != 0) dev_warn(xpc_part, "can't register die notifier\n"); /* * The real work-horse behind xpc. This processes incoming * interrupts and monitors remote heartbeats. */ kthread = kthread_run(xpc_hb_checker, NULL, XPC_HB_CHECK_THREAD_NAME); if (IS_ERR(kthread)) { dev_err(xpc_part, "failed while forking hb check thread\n"); ret = -EBUSY; goto out_3; } /* * Startup a thread that will attempt to discover other partitions to * activate based on info provided by SAL. This new thread is short * lived and will exit once discovery is complete. */ kthread = kthread_run(xpc_initiate_discovery, NULL, XPC_DISCOVERY_THREAD_NAME); if (IS_ERR(kthread)) { dev_err(xpc_part, "failed while forking discovery thread\n"); /* mark this new thread as a non-starter */ complete(&xpc_discovery_exited); xpc_do_exit(xpUnloading); return -EBUSY; } /* set the interface to point at XPC's functions */ xpc_set_interface(xpc_initiate_connect, xpc_initiate_disconnect, xpc_initiate_send, xpc_initiate_send_notify, xpc_initiate_received, xpc_initiate_partid_to_nasids); return 0; /* initialization was not successful */ out_3: xpc_teardown_rsvd_page(); (void)unregister_die_notifier(&xpc_die_notifier); (void)unregister_reboot_notifier(&xpc_reboot_notifier); out_2: if (xpc_sysctl) unregister_sysctl_table(xpc_sysctl); xpc_teardown_partitions(); out_1: if (is_shub()) xpc_exit_sn2(); else if (is_uv()) xpc_exit_uv(); return ret; }
static long wafwdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { int new_timeout; void __user *argp = (void __user *)arg; int __user *p = argp; static const struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, .firmware_version = 1, .identity = "Wafer 5823 WDT", }; switch (cmd) { case WDIOC_GETSUPPORT: if (copy_to_user(argp, &ident, sizeof(ident))) return -EFAULT; break; case WDIOC_GETSTATUS: case WDIOC_GETBOOTSTATUS: return put_user(0, p); case WDIOC_SETOPTIONS: { int options, retval = -EINVAL; if (get_user(options, p)) return -EFAULT; if (options & WDIOS_DISABLECARD) { wafwdt_start(); retval = 0; } if (options & WDIOS_ENABLECARD) { wafwdt_stop(); retval = 0; } return retval; } case WDIOC_KEEPALIVE: wafwdt_ping(); break; case WDIOC_SETTIMEOUT: if (get_user(new_timeout, p)) return -EFAULT; if ((new_timeout < 1) || (new_timeout > 255)) return -EINVAL; timeout = new_timeout; wafwdt_stop(); wafwdt_start(); /* Fall */ case WDIOC_GETTIMEOUT: return put_user(timeout, p); default: return -ENOTTY; } return 0; } static int wafwdt_open(struct inode *inode, struct file *file) { if (test_and_set_bit(0, &wafwdt_is_open)) return -EBUSY; /* * Activate */ wafwdt_start(); return nonseekable_open(inode, file); } static int wafwdt_close(struct inode *inode, struct file *file) { if (expect_close == 42) wafwdt_stop(); else { // printk(KERN_CRIT PFX ; wafwdt_ping(); } clear_bit(0, &wafwdt_is_open); expect_close = 0; return 0; } /* * Notifier for system down */ static int wafwdt_notify_sys(struct notifier_block *this, unsigned long code, void *unused) { if (code == SYS_DOWN || code == SYS_HALT) wafwdt_stop(); return NOTIFY_DONE; } /* * Kernel Interfaces */ static const struct file_operations wafwdt_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .write = wafwdt_write, .unlocked_ioctl = wafwdt_ioctl, .open = wafwdt_open, .release = wafwdt_close, }; static struct miscdevice wafwdt_miscdev = { .minor = WATCHDOG_MINOR, .name = "watchdog", .fops = &wafwdt_fops, }; /* * The WDT needs to learn about soft shutdowns in order to * turn the timebomb registers off. */ static struct notifier_block wafwdt_notifier = { .notifier_call = wafwdt_notify_sys, }; static int __init wafwdt_init(void) { int ret; // printk(KERN_INFO ; if (timeout < 1 || timeout > 255) { timeout = WD_TIMO; // printk(KERN_INFO PFX // "timeout value must be 1 <= x <= 255, using %d\n", ; } if (wdt_stop != wdt_start) { if (!request_region(wdt_stop, 1, "Wafer 5823 WDT")) { // printk(KERN_ERR PFX // "I/O address 0x%04x already in use\n", ; ret = -EIO; goto error; } } if (!request_region(wdt_start, 1, "Wafer 5823 WDT")) { // printk(KERN_ERR PFX "I/O address 0x%04x already in use\n", ; ret = -EIO; goto error2; } ret = register_reboot_notifier(&wafwdt_notifier); if (ret != 0) { // printk(KERN_ERR PFX ; goto error3; } ret = misc_register(&wafwdt_miscdev); if (ret != 0) { // printk(KERN_ERR PFX // "cannot register miscdev on minor=%d (err=%d)\n", ; goto error4; } // printk(KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d)\n", ; return ret; error4: unregister_reboot_notifier(&wafwdt_notifier); error3: release_region(wdt_start, 1); error2: if (wdt_stop != wdt_start) release_region(wdt_stop, 1); error: return ret; } static void __exit wafwdt_exit(void) { misc_deregister(&wafwdt_miscdev); unregister_reboot_notifier(&wafwdt_notifier); if (wdt_stop != wdt_start) release_region(wdt_stop, 1); release_region(wdt_start, 1); }
static long epx_c3_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { int options, retval = -EINVAL; int __user *argp = (void __user *)arg; static const struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING, .firmware_version = 0, .identity = "Winsystems EPX-C3 H/W Watchdog", }; switch (cmd) { case WDIOC_GETSUPPORT: if (copy_to_user(argp, &ident, sizeof(ident))) return -EFAULT; return 0; case WDIOC_GETSTATUS: case WDIOC_GETBOOTSTATUS: return put_user(0, argp); case WDIOC_SETOPTIONS: if (get_user(options, argp)) return -EFAULT; if (options & WDIOS_DISABLECARD) { epx_c3_stop(); retval = 0; } if (options & WDIOS_ENABLECARD) { epx_c3_start(); retval = 0; } return retval; case WDIOC_KEEPALIVE: epx_c3_pet(); return 0; case WDIOC_GETTIMEOUT: return put_user(WATCHDOG_TIMEOUT, argp); default: return -ENOTTY; } } static int epx_c3_notify_sys(struct notifier_block *this, unsigned long code, void *unused) { if (code == SYS_DOWN || code == SYS_HALT) epx_c3_stop(); /* Turn the WDT off */ return NOTIFY_DONE; } static const struct file_operations epx_c3_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .write = epx_c3_write, .unlocked_ioctl = epx_c3_ioctl, .open = epx_c3_open, .release = epx_c3_release, }; static struct miscdevice epx_c3_miscdev = { .minor = WATCHDOG_MINOR, .name = "watchdog", .fops = &epx_c3_fops, }; static struct notifier_block epx_c3_notifier = { .notifier_call = epx_c3_notify_sys, }; static const char banner[] __initconst = KERN_INFO PFX "Hardware Watchdog Timer for Winsystems EPX-C3 SBC: 0.1\n"; static int __init watchdog_init(void) { int ret; if (!request_region(EPXC3_WATCHDOG_CTL_REG, 2, "epxc3_watchdog")) return -EBUSY; ret = register_reboot_notifier(&epx_c3_notifier); if (ret) { printk(KERN_ERR PFX "cannot register reboot notifier " "(err=%d)\n", ret); goto out; } ret = misc_register(&epx_c3_miscdev); if (ret) { printk(KERN_ERR PFX "cannot register miscdev on minor=%d " "(err=%d)\n", WATCHDOG_MINOR, ret); unregister_reboot_notifier(&epx_c3_notifier); goto out; } printk(banner); return 0; out: release_region(EPXC3_WATCHDOG_CTL_REG, 2); return ret; } static void __exit watchdog_exit(void) { misc_deregister(&epx_c3_miscdev); unregister_reboot_notifier(&epx_c3_notifier); release_region(EPXC3_WATCHDOG_CTL_REG, 2); }
static long pnx833x_wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { int options, new_timeout = 0; uint32_t timeout, timeout_left = 0; static const struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT, .firmware_version = 0, .identity = "Hardware Watchdog for PNX833x", }; switch (cmd) { default: return -ENOTTY; case WDIOC_GETSUPPORT: if (copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))) return -EFAULT; return 0; case WDIOC_GETSTATUS: case WDIOC_GETBOOTSTATUS: return put_user(0, (int *)arg); case WDIOC_SETOPTIONS: if (get_user(options, (int *)arg)) return -EFAULT; if (options & WDIOS_DISABLECARD) pnx833x_wdt_stop(); if (options & WDIOS_ENABLECARD) pnx833x_wdt_start(); return 0; case WDIOC_KEEPALIVE: pnx833x_wdt_ping(); return 0; case WDIOC_SETTIMEOUT: { if (get_user(new_timeout, (int *)arg)) return -EFAULT; pnx833x_wdt_timeout = new_timeout; PNX833X_REG(PNX833X_CONFIG + PNX833X_CONFIG_CPU_WATCHDOG_COMPARE) = new_timeout; return put_user(new_timeout, (int *)arg); } case WDIOC_GETTIMEOUT: timeout = PNX833X_REG(PNX833X_CONFIG + PNX833X_CONFIG_CPU_WATCHDOG_COMPARE); return put_user(timeout, (int *)arg); case WDIOC_GETTIMELEFT: timeout_left = PNX833X_REG(PNX833X_CONFIG + PNX833X_CONFIG_CPU_WATCHDOG); return put_user(timeout_left, (int *)arg); } } static int pnx833x_wdt_notify_sys(struct notifier_block *this, unsigned long code, void *unused) { if (code == SYS_DOWN || code == SYS_HALT) pnx833x_wdt_stop(); /* Turn the WDT off */ return NOTIFY_DONE; } static const struct file_operations pnx833x_wdt_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .write = pnx833x_wdt_write, .unlocked_ioctl = pnx833x_wdt_ioctl, .open = pnx833x_wdt_open, .release = pnx833x_wdt_release, }; static struct miscdevice pnx833x_wdt_miscdev = { .minor = WATCHDOG_MINOR, .name = "watchdog", .fops = &pnx833x_wdt_fops, }; static struct notifier_block pnx833x_wdt_notifier = { .notifier_call = pnx833x_wdt_notify_sys, }; static int __init watchdog_init(void) { int ret, cause; /* Lets check the reason for the reset.*/ cause = PNX833X_REG(PNX833X_RESET); /*If bit 31 is set then watchdog was cause of reset.*/ if (cause & 0x80000000) { pr_info("The system was previously reset due to the watchdog firing - please investigate...\n"); } ret = register_reboot_notifier(&pnx833x_wdt_notifier); if (ret) { pr_err("cannot register reboot notifier (err=%d)\n", ret); return ret; } ret = misc_register(&pnx833x_wdt_miscdev); if (ret) { pr_err("cannot register miscdev on minor=%d (err=%d)\n", WATCHDOG_MINOR, ret); unregister_reboot_notifier(&pnx833x_wdt_notifier); return ret; } pr_info("Hardware Watchdog Timer for PNX833x: Version 0.1\n"); if (start_enabled) pnx833x_wdt_start(); return 0; } static void __exit watchdog_exit(void) { misc_deregister(&pnx833x_wdt_miscdev); unregister_reboot_notifier(&pnx833x_wdt_notifier); }
static long fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { void __user *argp = (void __user *)arg; int __user *p = argp; static const struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, .firmware_version = 1, .identity = "W83877F", }; switch (cmd) { case WDIOC_GETSUPPORT: return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; case WDIOC_GETSTATUS: case WDIOC_GETBOOTSTATUS: return put_user(0, p); case WDIOC_SETOPTIONS: { int new_options, retval = -EINVAL; if (get_user(new_options, p)) return -EFAULT; if (new_options & WDIOS_DISABLECARD) { wdt_turnoff(); retval = 0; } if (new_options & WDIOS_ENABLECARD) { wdt_startup(); retval = 0; } return retval; } case WDIOC_KEEPALIVE: wdt_keepalive(); return 0; case WDIOC_SETTIMEOUT: { int new_timeout; if (get_user(new_timeout, p)) return -EFAULT; /* arbitrary upper limit */ if (new_timeout < 1 || new_timeout > 3600) return -EINVAL; timeout = new_timeout; wdt_keepalive(); /* Fall through */ } case WDIOC_GETTIMEOUT: return put_user(timeout, p); default: return -ENOTTY; } } static const struct file_operations wdt_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .write = fop_write, .open = fop_open, .release = fop_close, .unlocked_ioctl = fop_ioctl, }; static struct miscdevice wdt_miscdev = { .minor = WATCHDOG_MINOR, .name = "watchdog", .fops = &wdt_fops, }; static int wdt_notify_sys(struct notifier_block *this, unsigned long code, void *unused) { if (code == SYS_DOWN || code == SYS_HALT) wdt_turnoff(); return NOTIFY_DONE; } static struct notifier_block wdt_notifier = { .notifier_call = wdt_notify_sys, }; static void __exit w83877f_wdt_unload(void) { wdt_turnoff(); /* Deregister */ misc_deregister(&wdt_miscdev); unregister_reboot_notifier(&wdt_notifier); release_region(WDT_PING, 1); release_region(ENABLE_W83877F_PORT, 2); } static int __init w83877f_wdt_init(void) { int rc = -EBUSY; if (timeout < 1 || timeout > 3600) { /* arbitrary upper limit */ timeout = WATCHDOG_TIMEOUT; printk(KERN_INFO PFX "timeout value must be 1 <= x <= 3600, using %d\n", timeout); } if (!request_region(ENABLE_W83877F_PORT, 2, "W83877F WDT")) { printk(KERN_ERR PFX "I/O address 0x%04x already in use\n", ENABLE_W83877F_PORT); rc = -EIO; goto err_out; } if (!request_region(WDT_PING, 1, "W8387FF WDT")) { printk(KERN_ERR PFX "I/O address 0x%04x already in use\n", WDT_PING); rc = -EIO; goto err_out_region1; } rc = register_reboot_notifier(&wdt_notifier); if (rc) { printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", rc); goto err_out_region2; } rc = misc_register(&wdt_miscdev); if (rc) { printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", wdt_miscdev.minor, rc); goto err_out_reboot; } printk(KERN_INFO PFX "WDT driver for W83877F initialised. timeout=%d sec (nowayout=%d)\n", timeout, nowayout); return 0; err_out_reboot: unregister_reboot_notifier(&wdt_notifier); err_out_region2: release_region(WDT_PING, 1); err_out_region1: release_region(ENABLE_W83877F_PORT, 2); err_out: return rc; }
static long wb_smsc_wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { int new_timeout; union { struct watchdog_info __user *ident; int __user *i; } uarg; static const struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, .firmware_version = 0, .identity = "SMsC 37B787 Watchdog", }; uarg.i = (int __user *)arg; switch (cmd) { case WDIOC_GETSUPPORT: return copy_to_user(uarg.ident, &ident, sizeof(ident)) ? -EFAULT : 0; case WDIOC_GETSTATUS: return put_user(wb_smsc_wdt_status(), uarg.i); case WDIOC_GETBOOTSTATUS: return put_user(0, uarg.i); case WDIOC_SETOPTIONS: { int options, retval = -EINVAL; if (get_user(options, uarg.i)) return -EFAULT; if (options & WDIOS_DISABLECARD) { wb_smsc_wdt_disable(); retval = 0; } if (options & WDIOS_ENABLECARD) { wb_smsc_wdt_enable(); retval = 0; } return retval; } case WDIOC_KEEPALIVE: wb_smsc_wdt_reset_timer(); return 0; case WDIOC_SETTIMEOUT: if (get_user(new_timeout, uarg.i)) return -EFAULT; /* the API states this is given in secs */ if (unit == UNIT_MINUTE) new_timeout /= 60; if (new_timeout < 0 || new_timeout > MAX_TIMEOUT) return -EINVAL; timeout = new_timeout; wb_smsc_wdt_set_timeout(timeout); /* fall through - and return the new timeout... */ case WDIOC_GETTIMEOUT: new_timeout = timeout; if (unit == UNIT_MINUTE) new_timeout *= 60; return put_user(new_timeout, uarg.i); default: return -ENOTTY; } } /* -- Notifier funtions -----------------------------------------*/ static int wb_smsc_wdt_notify_sys(struct notifier_block *this, unsigned long code, void *unused) { if (code == SYS_DOWN || code == SYS_HALT) { /* set timeout to 0, to avoid possible race-condition */ timeout = 0; wb_smsc_wdt_disable(); } return NOTIFY_DONE; } /* -- Module's structures ---------------------------------------*/ static const struct file_operations wb_smsc_wdt_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .write = wb_smsc_wdt_write, .unlocked_ioctl = wb_smsc_wdt_ioctl, .open = wb_smsc_wdt_open, .release = wb_smsc_wdt_release, }; static struct notifier_block wb_smsc_wdt_notifier = { .notifier_call = wb_smsc_wdt_notify_sys, }; static struct miscdevice wb_smsc_wdt_miscdev = { .minor = WATCHDOG_MINOR, .name = "watchdog", .fops = &wb_smsc_wdt_fops, }; /* -- Module init functions -------------------------------------*/ /* module's "constructor" */ static int __init wb_smsc_wdt_init(void) { int ret; pr_info("SMsC 37B787 watchdog component driver " VERSION " initialising...\n"); if (!request_region(IOPORT, IOPORT_SIZE, "SMsC 37B787 watchdog")) { pr_err("Unable to register IO port %#x\n", IOPORT); ret = -EBUSY; goto out_pnp; } /* set new maximum, if it's too big */ if (timeout > MAX_TIMEOUT) timeout = MAX_TIMEOUT; /* init the watchdog timer */ wb_smsc_wdt_initialize(); ret = register_reboot_notifier(&wb_smsc_wdt_notifier); if (ret) { pr_err("Unable to register reboot notifier err = %d\n", ret); goto out_io; } ret = misc_register(&wb_smsc_wdt_miscdev); if (ret) { pr_err("Unable to register miscdev on minor %d\n", WATCHDOG_MINOR); goto out_rbt; } /* output info */ pr_info("Timeout set to %d %s\n", timeout, (unit == UNIT_SECOND) ? "second(s)" : "minute(s)"); pr_info("Watchdog initialized and sleeping (nowayout=%d)...\n", nowayout); out_clean: return ret; out_rbt: unregister_reboot_notifier(&wb_smsc_wdt_notifier); out_io: release_region(IOPORT, IOPORT_SIZE); out_pnp: goto out_clean; } /* module's "destructor" */ static void __exit wb_smsc_wdt_exit(void) { /* Stop the timer before we leave */ if (!nowayout) { wb_smsc_wdt_shutdown(); pr_info("Watchdog disabled\n"); } misc_deregister(&wb_smsc_wdt_miscdev); unregister_reboot_notifier(&wb_smsc_wdt_notifier); release_region(IOPORT, IOPORT_SIZE); pr_info("SMsC 37B787 watchdog component driver removed\n"); } module_init(wb_smsc_wdt_init); module_exit(wb_smsc_wdt_exit); MODULE_AUTHOR("Sven Anders <*****@*****.**>"); MODULE_DESCRIPTION("Driver for SMsC 37B787 watchdog component (Version " VERSION ")"); MODULE_LICENSE("GPL"); #ifdef SMSC_SUPPORT_MINUTES module_param(unit, int, 0); MODULE_PARM_DESC(unit, "set unit to use, 0=seconds or 1=minutes, default is 0"); #endif module_param(timeout, int, 0); MODULE_PARM_DESC(timeout, "range is 1-255 units, default is 60"); module_param(nowayout, bool, 0); MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
static long fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { void __user *argp = (void __user *)arg; int __user *p = argp; static const struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, .firmware_version = 1, .identity = "ALiM7101", }; switch (cmd) { case WDIOC_GETSUPPORT: return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; case WDIOC_GETSTATUS: case WDIOC_GETBOOTSTATUS: return put_user(0, p); case WDIOC_SETOPTIONS: { int new_options, retval = -EINVAL; if (get_user(new_options, p)) return -EFAULT; if (new_options & WDIOS_DISABLECARD) { wdt_turnoff(); retval = 0; } if (new_options & WDIOS_ENABLECARD) { wdt_startup(); retval = 0; } return retval; } case WDIOC_KEEPALIVE: wdt_keepalive(); return 0; case WDIOC_SETTIMEOUT: { int new_timeout; if (get_user(new_timeout, p)) return -EFAULT; /* arbitrary upper limit */ if (new_timeout < 1 || new_timeout > 3600) return -EINVAL; timeout = new_timeout; wdt_keepalive(); /* Fall through */ } case WDIOC_GETTIMEOUT: return put_user(timeout, p); default: return -ENOTTY; } } static const struct file_operations wdt_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .write = fop_write, .open = fop_open, .release = fop_close, .unlocked_ioctl = fop_ioctl, }; static struct miscdevice wdt_miscdev = { .minor = WATCHDOG_MINOR, .name = "watchdog", .fops = &wdt_fops, }; /* * Notifier for system down */ static int wdt_notify_sys(struct notifier_block *this, unsigned long code, void *unused) { if (code == SYS_DOWN || code == SYS_HALT) wdt_turnoff(); if (code == SYS_RESTART) { /* * Cobalt devices have no way of rebooting themselves other * than getting the watchdog to pull reset, so we restart the * watchdog on reboot with no heartbeat */ wdt_change(WDT_ENABLE); printk(KERN_INFO PFX "Watchdog timer is now enabled " "with no heartbeat - should reboot in ~1 second.\n"); } return NOTIFY_DONE; } /* * The WDT needs to learn about soft shutdowns in order to * turn the timebomb registers off. */ static struct notifier_block wdt_notifier = { .notifier_call = wdt_notify_sys, }; static void __exit alim7101_wdt_unload(void) { wdt_turnoff(); /* Deregister */ misc_deregister(&wdt_miscdev); unregister_reboot_notifier(&wdt_notifier); pci_dev_put(alim7101_pmu); } static int __init alim7101_wdt_init(void) { int rc = -EBUSY; struct pci_dev *ali1543_south; char tmp; printk(KERN_INFO PFX "Steve Hill <*****@*****.**>.\n"); alim7101_pmu = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, NULL); if (!alim7101_pmu) { printk(KERN_INFO PFX "ALi M7101 PMU not present - WDT not set\n"); return -EBUSY; } /* Set the WDT in the PMU to 1 second */ pci_write_config_byte(alim7101_pmu, ALI_7101_WDT, 0x02); ali1543_south = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL); if (!ali1543_south) { printk(KERN_INFO PFX "ALi 1543 South-Bridge not present - WDT not set\n"); goto err_out; } pci_read_config_byte(ali1543_south, 0x5e, &tmp); pci_dev_put(ali1543_south); if ((tmp & 0x1e) == 0x00) { if (!use_gpio) { printk(KERN_INFO PFX "Detected old alim7101 revision 'a1d'. " "If this is a cobalt board, set the 'use_gpio' " "module parameter.\n"); goto err_out; } nowayout = 1; } else if ((tmp & 0x1e) != 0x12 && (tmp & 0x1e) != 0x00) { printk(KERN_INFO PFX "ALi 1543 South-Bridge does not have the correct " "revision number (???1001?) - WDT not set\n"); goto err_out; } if (timeout < 1 || timeout > 3600) { /* arbitrary upper limit */ timeout = WATCHDOG_TIMEOUT; printk(KERN_INFO PFX "timeout value must be 1 <= x <= 3600, using %d\n", timeout); } rc = register_reboot_notifier(&wdt_notifier); if (rc) { printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", rc); goto err_out; } rc = misc_register(&wdt_miscdev); if (rc) { printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", wdt_miscdev.minor, rc); goto err_out_reboot; } if (nowayout) __module_get(THIS_MODULE); printk(KERN_INFO PFX "WDT driver for ALi M7101 initialised. " "timeout=%d sec (nowayout=%d)\n", timeout, nowayout); return 0; err_out_reboot: unregister_reboot_notifier(&wdt_notifier); err_out: pci_dev_put(alim7101_pmu); return rc; }
static int acq_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { int options, retval = -EINVAL; void __user *argp = (void __user *)arg; int __user *p = argp; static struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, .firmware_version = 1, .identity = "Acquire WDT", }; switch(cmd) { case WDIOC_GETSUPPORT: return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; case WDIOC_GETSTATUS: case WDIOC_GETBOOTSTATUS: return put_user(0, p); case WDIOC_KEEPALIVE: acq_keepalive(); return 0; case WDIOC_GETTIMEOUT: return put_user(WATCHDOG_HEARTBEAT, p); case WDIOC_SETOPTIONS: { if (get_user(options, p)) return -EFAULT; if (options & WDIOS_DISABLECARD) { acq_stop(); retval = 0; } if (options & WDIOS_ENABLECARD) { acq_keepalive(); retval = 0; } return retval; } default: return -ENOTTY; } } static int acq_open(struct inode *inode, struct file *file) { if (test_and_set_bit(0, &acq_is_open)) return -EBUSY; if (nowayout) __module_get(THIS_MODULE); /* Activate */ acq_keepalive(); return nonseekable_open(inode, file); } static int acq_close(struct inode *inode, struct file *file) { if (expect_close == 42) { acq_stop(); } else { printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); acq_keepalive(); } clear_bit(0, &acq_is_open); expect_close = 0; return 0; } /* * Notifier for system down */ static int acq_notify_sys(struct notifier_block *this, unsigned long code, void *unused) { if(code==SYS_DOWN || code==SYS_HALT) { /* Turn the WDT off */ acq_stop(); } return NOTIFY_DONE; } /* * Kernel Interfaces */ static const struct file_operations acq_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .write = acq_write, .ioctl = acq_ioctl, .open = acq_open, .release = acq_close, }; static struct miscdevice acq_miscdev= { .minor = WATCHDOG_MINOR, .name = "watchdog", .fops = &acq_fops, }; /* * The WDT card needs to learn about soft shutdowns in order to * turn the timebomb registers off. */ static struct notifier_block acq_notifier = { .notifier_call = acq_notify_sys, }; static int __init acq_init(void) { int ret; printk(KERN_INFO "WDT driver for Acquire single board computer initialising.\n"); if (wdt_stop != wdt_start) { if (!request_region(wdt_stop, 1, WATCHDOG_NAME)) { printk (KERN_ERR PFX "I/O address 0x%04x already in use\n", wdt_stop); ret = -EIO; goto out; } } if (!request_region(wdt_start, 1, WATCHDOG_NAME)) { printk (KERN_ERR PFX "I/O address 0x%04x already in use\n", wdt_start); ret = -EIO; goto unreg_stop; } ret = register_reboot_notifier(&acq_notifier); if (ret != 0) { printk (KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", ret); goto unreg_regions; } ret = misc_register(&acq_miscdev); if (ret != 0) { printk (KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", WATCHDOG_MINOR, ret); goto unreg_reboot; } printk (KERN_INFO PFX "initialized. (nowayout=%d)\n", nowayout); return 0; unreg_reboot: unregister_reboot_notifier(&acq_notifier); unreg_regions: release_region(wdt_start, 1); unreg_stop: if (wdt_stop != wdt_start) release_region(wdt_stop, 1); out: return ret; } static void __exit acq_exit(void) { misc_deregister(&acq_miscdev); unregister_reboot_notifier(&acq_notifier); if(wdt_stop != wdt_start) release_region(wdt_stop,1); release_region(wdt_start,1); }
static int fop_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { void __user *argp = (void __user *)arg; int __user *p = argp; static struct watchdog_info ident= { .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, .firmware_version = 1, .identity = "SBC60xx", }; switch(cmd) { default: return -ENOTTY; case WDIOC_GETSUPPORT: return copy_to_user(argp, &ident, sizeof(ident))?-EFAULT:0; case WDIOC_GETSTATUS: case WDIOC_GETBOOTSTATUS: return put_user(0, p); case WDIOC_KEEPALIVE: wdt_keepalive(); return 0; case WDIOC_SETOPTIONS: { int new_options, retval = -EINVAL; if(get_user(new_options, p)) return -EFAULT; if(new_options & WDIOS_DISABLECARD) { wdt_turnoff(); retval = 0; } if(new_options & WDIOS_ENABLECARD) { wdt_startup(); retval = 0; } return retval; } case WDIOC_SETTIMEOUT: { int new_timeout; if(get_user(new_timeout, p)) return -EFAULT; if(new_timeout < 1 || new_timeout > 3600) /* arbitrary upper limit */ return -EINVAL; timeout = new_timeout; wdt_keepalive(); /* Fall through */ } case WDIOC_GETTIMEOUT: return put_user(timeout, p); } } static const struct file_operations wdt_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .write = fop_write, .open = fop_open, .release = fop_close, .ioctl = fop_ioctl, }; static struct miscdevice wdt_miscdev = { .minor = WATCHDOG_MINOR, .name = "watchdog", .fops = &wdt_fops, }; /* * Notifier for system down */ static int wdt_notify_sys(struct notifier_block *this, unsigned long code, void *unused) { if(code==SYS_DOWN || code==SYS_HALT) wdt_turnoff(); return NOTIFY_DONE; } /* * The WDT needs to learn about soft shutdowns in order to * turn the timebomb registers off. */ static struct notifier_block wdt_notifier= { .notifier_call = wdt_notify_sys, }; static void __exit sbc60xxwdt_unload(void) { wdt_turnoff(); /* Deregister */ misc_deregister(&wdt_miscdev); unregister_reboot_notifier(&wdt_notifier); if ((wdt_stop != 0x45) && (wdt_stop != wdt_start)) release_region(wdt_stop,1); release_region(wdt_start,1); } static int __init sbc60xxwdt_init(void) { int rc = -EBUSY; if(timeout < 1 || timeout > 3600) /* arbitrary upper limit */ { timeout = WATCHDOG_TIMEOUT; printk(KERN_INFO PFX "timeout value must be 1<=x<=3600, using %d\n", timeout); } if (!request_region(wdt_start, 1, "SBC 60XX WDT")) { printk(KERN_ERR PFX "I/O address 0x%04x already in use\n", wdt_start); rc = -EIO; goto err_out; } /* We cannot reserve 0x45 - the kernel already has! */ if ((wdt_stop != 0x45) && (wdt_stop != wdt_start)) { if (!request_region(wdt_stop, 1, "SBC 60XX WDT")) { printk(KERN_ERR PFX "I/O address 0x%04x already in use\n", wdt_stop); rc = -EIO; goto err_out_region1; } } init_timer(&timer); timer.function = wdt_timer_ping; timer.data = 0; rc = misc_register(&wdt_miscdev); if (rc) { printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", wdt_miscdev.minor, rc); goto err_out_region2; } rc = register_reboot_notifier(&wdt_notifier); if (rc) { printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", rc); goto err_out_miscdev; } printk(KERN_INFO PFX "WDT driver for 60XX single board computer initialised. timeout=%d sec (nowayout=%d)\n", timeout, nowayout); return 0; err_out_miscdev: misc_deregister(&wdt_miscdev); err_out_region2: if ((wdt_stop != 0x45) && (wdt_stop != wdt_start)) release_region(wdt_stop,1); err_out_region1: release_region(wdt_start,1); err_out: return rc; }
static int exynos5_devfreq_int_probe(struct platform_device *pdev) { int ret = 0; struct devfreq_data_int *data; struct devfreq_notifier_block *devfreq_nb; struct exynos_devfreq_platdata *plat_data; data = kzalloc(sizeof(struct devfreq_data_int), GFP_KERNEL); if (data == NULL) { pr_err("DEVFREQ(INT) : Failed to allocate private data\n"); ret = -ENOMEM; goto err_data; } exynos5433_devfreq_int_init(data); data->initial_freq = exynos5_devfreq_int_profile.initial_freq; exynos5_devfreq_int_profile.freq_table = kzalloc(sizeof(int) * data->max_state, GFP_KERNEL); if (exynos5_devfreq_int_profile.freq_table == NULL) { pr_err("DEVFREQ(INT) : Failed to allocate freq table\n"); ret = -ENOMEM; goto err_freqtable; } ret = exynos5_init_int_table(&pdev->dev, data); if (ret) goto err_inittable; platform_set_drvdata(pdev, data); mutex_init(&data->lock); data->target_volt = get_match_volt(ID_INT, DEVFREQ_INITIAL_FREQ); data->volt_constraint_isp = 0; data->volt_offset = 0; int_dev = data->dev = &pdev->dev; data->vdd_int = regulator_get(NULL, "vdd_int"); if (IS_ERR_OR_NULL(data->vdd_int)) { pr_err("DEVFREQ(INT) : Failed to get regulator\n"); goto err_inittable; } data->vdd_int_m = regulator_get(NULL, "vdd_int_m"); if (IS_ERR(data->vdd_int)) { dev_err(data->dev, "DEVFREQ(INT) : failed to get regulator\n"); goto err_regulator_m; } data->devfreq = devfreq_add_device(data->dev, &exynos5_devfreq_int_profile, "simple_ondemand", &exynos5_devfreq_int_governor_data); devfreq_nb = kzalloc(sizeof(struct devfreq_notifier_block), GFP_KERNEL); if (devfreq_nb == NULL) { pr_err("DEVFREQ(INT) : Failed to allocate notifier block\n"); ret = -ENOMEM; goto err_nb; } devfreq_nb->df = data->devfreq; devfreq_nb->nb.notifier_call = exynos5_devfreq_int_notifier; exynos5433_devfreq_register(&devfreq_int_exynos); exynos5433_ppmu_register_notifier(INT, &devfreq_nb->nb); plat_data = data->dev->platform_data; data->default_qos = plat_data->default_qos; data->devfreq->min_freq = plat_data->default_qos; data->devfreq->max_freq = devfreq_int_opp_list[0].freq; register_reboot_notifier(&exynos5_int_reboot_notifier); #ifdef CONFIG_EXYNOS_THERMAL data->tmu_notifier.notifier_call = exynos5_devfreq_int_tmu_notifier; exynos_tmu_add_notifier(&data->tmu_notifier); #endif data->use_dvfs = true; return ret; err_nb: devfreq_remove_device(data->devfreq); regulator_put(data->vdd_int_m); err_regulator_m: regulator_put(data->vdd_int); err_inittable: kfree(exynos5_devfreq_int_profile.freq_table); err_freqtable: kfree(data); err_data: return ret; }
static int wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { void __user *argp = (void __user *)arg; int __user *p = argp; int new_timeout; static struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, .firmware_version = 1, .identity = "W83627HF WDT", }; switch (cmd) { case WDIOC_GETSUPPORT: if (copy_to_user(argp, &ident, sizeof(ident))) return -EFAULT; break; case WDIOC_GETSTATUS: case WDIOC_GETBOOTSTATUS: return put_user(0, p); case WDIOC_KEEPALIVE: wdt_ping(); break; case WDIOC_SETTIMEOUT: if (get_user(new_timeout, p)) return -EFAULT; if (wdt_set_heartbeat(new_timeout)) return -EINVAL; wdt_ping(); /* Fall */ case WDIOC_GETTIMEOUT: return put_user(timeout, p); case WDIOC_SETOPTIONS: { int options, retval = -EINVAL; if (get_user(options, p)) return -EFAULT; if (options & WDIOS_DISABLECARD) { wdt_disable(); retval = 0; } if (options & WDIOS_ENABLECARD) { wdt_ping(); retval = 0; } return retval; } default: return -ENOIOCTLCMD; } return 0; } static int wdt_open(struct inode *inode, struct file *file) { if (test_and_set_bit(0, &wdt_is_open)) return -EBUSY; /* * Activate */ wdt_ping(); return nonseekable_open(inode, file); } static int wdt_close(struct inode *inode, struct file *file) { if (expect_close == 42) { wdt_disable(); } else { printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); wdt_ping(); } expect_close = 0; clear_bit(0, &wdt_is_open); return 0; } /* * Notifier for system down */ static int wdt_notify_sys(struct notifier_block *this, unsigned long code, void *unused) { if (code == SYS_DOWN || code == SYS_HALT) { /* Turn the WDT off */ wdt_disable(); } return NOTIFY_DONE; } /* * Kernel Interfaces */ static struct file_operations wdt_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .write = wdt_write, .ioctl = wdt_ioctl, .open = wdt_open, .release = wdt_close, }; static struct miscdevice wdt_miscdev = { .minor = WATCHDOG_MINOR, .name = "watchdog", .fops = &wdt_fops, }; /* * The WDT needs to learn about soft shutdowns in order to * turn the timebomb registers off. */ static struct notifier_block wdt_notifier = { .notifier_call = wdt_notify_sys, }; static int __init wdt_init(void) { int ret; printk(KERN_INFO "WDT driver for the Winbond(TM) W83627HF Super I/O chip initialising.\n"); if (wdt_set_heartbeat(timeout)) { wdt_set_heartbeat(WATCHDOG_TIMEOUT); printk (KERN_INFO PFX "timeout value must be 1<=timeout<=63, using %d\n", WATCHDOG_TIMEOUT); } if (!request_region(wdt_io, 1, WATCHDOG_NAME)) { printk (KERN_ERR PFX "I/O address 0x%04x already in use\n", wdt_io); ret = -EIO; goto out; } w83627hf_init(); ret = register_reboot_notifier(&wdt_notifier); if (ret != 0) { printk (KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", ret); goto unreg_regions; } ret = misc_register(&wdt_miscdev); if (ret != 0) { printk (KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", WATCHDOG_MINOR, ret); goto unreg_reboot; } printk (KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d)\n", timeout, nowayout); out: return ret; unreg_reboot: unregister_reboot_notifier(&wdt_notifier); unreg_regions: release_region(wdt_io, 1); goto out; } static void __exit wdt_exit(void) { misc_deregister(&wdt_miscdev); unregister_reboot_notifier(&wdt_notifier); release_region(wdt_io,1); }
static int softdog_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { void __user *argp = (void __user *)arg; int __user *p = argp; int new_margin; static struct watchdog_info ident = { .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, .firmware_version = 0, .identity = "Software Watchdog", }; switch (cmd) { default: return -ENOTTY; case WDIOC_GETSUPPORT: return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; case WDIOC_GETSTATUS: case WDIOC_GETBOOTSTATUS: return put_user(0, p); case WDIOC_KEEPALIVE: softdog_keepalive(); return 0; case WDIOC_SETTIMEOUT: if (get_user(new_margin, p)) return -EFAULT; if (softdog_set_heartbeat(new_margin)) return -EINVAL; softdog_keepalive(); /* Fall */ case WDIOC_GETTIMEOUT: return put_user(soft_margin, p); } } /* * Notifier for system down */ static int softdog_notify_sys(struct notifier_block *this, unsigned long code, void *unused) { if(code==SYS_DOWN || code==SYS_HALT) { /* Turn the WDT off */ softdog_stop(); } return NOTIFY_DONE; } /* * Kernel Interfaces */ static const struct file_operations softdog_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .write = softdog_write, .ioctl = softdog_ioctl, .open = softdog_open, .release = softdog_release, }; static struct miscdevice softdog_miscdev = { .minor = WATCHDOG_MINOR, .name = "watchdog", .fops = &softdog_fops, }; static struct notifier_block softdog_notifier = { .notifier_call = softdog_notify_sys, }; static char banner[] __initdata = KERN_INFO "Software Watchdog Timer: 0.07 initialized. soft_noboot=%d soft_margin=%d sec (nowayout= %d)\n"; static int __init watchdog_init(void) { int ret; /* Check that the soft_margin value is within it's range ; if not reset to the default */ if (softdog_set_heartbeat(soft_margin)) { softdog_set_heartbeat(TIMER_MARGIN); printk(KERN_INFO PFX "soft_margin value must be 0<soft_margin<65536, using %d\n", TIMER_MARGIN); } ret = register_reboot_notifier(&softdog_notifier); if (ret) { printk (KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", ret); return ret; } ret = misc_register(&softdog_miscdev); if (ret) { printk (KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", WATCHDOG_MINOR, ret); unregister_reboot_notifier(&softdog_notifier); return ret; } printk(banner, soft_noboot, soft_margin, nowayout); return 0; } static void __exit watchdog_exit(void) { misc_deregister(&softdog_miscdev); unregister_reboot_notifier(&softdog_notifier); }