static int __orderly_poweroff(bool force) { char **argv; static char *envp[] = { "HOME=/", "PATH=/sbin:/bin:/usr/sbin:/usr/bin", NULL }; int ret; argv = argv_split(GFP_KERNEL, poweroff_cmd, NULL); if (argv) { ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC); argv_free(argv); } else { ret = -ENOMEM; } if (ret && force) { pr_warn("Failed to start orderly shutdown: forcing the issue\n"); /* * I guess this should try to kick off some daemon to sync and * poweroff asap. Or not even bother syncing if we're doing an * emergency shutdown? */ emergency_sync(); kernel_power_off(); } return ret; }
static void rtas_parse_epow_errlog(struct rtas_error_log *log) { struct pseries_errorlog *pseries_log; struct epow_errorlog *epow_log; char action_code; char modifier; pseries_log = get_pseries_errorlog(log, PSERIES_ELOG_SECT_ID_EPOW); if (pseries_log == NULL) return; epow_log = (struct epow_errorlog *)pseries_log->data; action_code = epow_log->sensor_value & 0xF; /* bottom 4 bits */ modifier = epow_log->event_modifier & 0xF; /* bottom 4 bits */ switch (action_code) { case EPOW_RESET: if (num_epow_events) { pr_info("Non critical power/cooling issue cleared\n"); num_epow_events--; } break; case EPOW_WARN_COOLING: pr_info("Non-critical cooling issue detected. Check RTAS error" " log for details\n"); break; case EPOW_WARN_POWER: pr_info("Non-critical power issue detected. Check RTAS error" " log for details\n"); break; case EPOW_SYSTEM_SHUTDOWN: handle_system_shutdown(epow_log->event_modifier); break; case EPOW_SYSTEM_HALT: pr_emerg("Critical power/cooling issue detected. Check RTAS" " error log for details. Powering off.\n"); orderly_poweroff(true); break; case EPOW_MAIN_ENCLOSURE: case EPOW_POWER_OFF: pr_emerg("System about to lose power. Check RTAS error log " " for details. Powering off immediately.\n"); emergency_sync(); kernel_power_off(); break; default: pr_err("Unknown power/cooling event (action code = %d)\n", action_code); } /* Increment epow events counter variable */ if (action_code != EPOW_RESET) num_epow_events++; }
void rtas_parse_epow_errlog(struct rtas_error_log *log) { struct pseries_errorlog *pseries_log; struct epow_errorlog *epow_log; char action_code; char modifier; pseries_log = get_pseries_errorlog(log, PSERIES_ELOG_SECT_ID_EPOW); if (pseries_log == NULL) return; epow_log = (struct epow_errorlog *)pseries_log->data; action_code = epow_log->sensor_value & 0xF; /* bottom 4 bits */ modifier = epow_log->event_modifier & 0xF; /* bottom 4 bits */ switch (action_code) { case EPOW_RESET: pr_err("Non critical power or cooling issue cleared"); break; case EPOW_WARN_COOLING: pr_err("Non critical cooling issue reported by firmware"); pr_err("Check RTAS error log for details"); break; case EPOW_WARN_POWER: pr_err("Non critical power issue reported by firmware"); pr_err("Check RTAS error log for details"); break; case EPOW_SYSTEM_SHUTDOWN: handle_system_shutdown(epow_log->event_modifier); break; case EPOW_SYSTEM_HALT: pr_emerg("Firmware initiated power off"); orderly_poweroff(1); break; case EPOW_MAIN_ENCLOSURE: case EPOW_POWER_OFF: pr_emerg("Critical power/cooling issue reported by firmware"); pr_emerg("Check RTAS error log for details"); pr_emerg("Immediate power off"); emergency_sync(); kernel_power_off(); break; default: pr_err("Unknown power/cooling event (action code %d)", action_code); } }
static int __orderly_reboot(void) { int ret; ret = run_cmd(reboot_cmd); if (ret) { pr_warn("Failed to start orderly reboot: forcing the issue\n"); emergency_sync(); kernel_restart(NULL); } return ret; }
static void handle_node_poweroff(struct rpc_desc *desc) { emergency_sync(); emergency_remount(); set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(5 * HZ); local_irq_enable(); kernel_power_off(); // should never be reached BUG(); }
/** * orderly_poweroff - Trigger an orderly system poweroff * @force: force poweroff if command execution fails * * This may be called from any context to trigger a system shutdown. * If the orderly shutdown fails, it will force an immediate shutdown. */ int orderly_poweroff(bool force) { int argc; char **argv = argv_split(GFP_ATOMIC, poweroff_cmd, &argc); static char *envp[] = { "HOME=/", "PATH=/sbin:/bin:/usr/sbin:/usr/bin", NULL }; int ret = -ENOMEM; struct subprocess_info *info; if (argv == NULL) { printk(KERN_WARNING "%s failed to allocate memory for \"%s\"\n", __func__, poweroff_cmd); goto out; } info = call_usermodehelper_setup(argv[0], argv, envp); if (info == NULL) { argv_free(argv); goto out; } call_usermodehelper_setcleanup(info, argv_cleanup); ret = call_usermodehelper_exec(info, UMH_NO_WAIT); out: if (ret && force) { printk(KERN_WARNING "Failed to start orderly shutdown: " "forcing the issue\n"); /* I guess this should try to kick off some daemon to sync and poweroff asap. Or not even bother syncing if we're doing an emergency shutdown? */ emergency_sync(); kernel_power_off(); } return ret; }
static int __orderly_poweroff(bool force) { int ret; ret = run_cmd(poweroff_cmd); if (ret && force) { pr_warn("Failed to start orderly shutdown: forcing the issue\n"); /* * I guess this should try to kick off some daemon to sync and * poweroff asap. Or not even bother syncing if we're doing an * emergency shutdown? */ emergency_sync(); kernel_power_off(); } return ret; }
/* * Handle hardware error interrupts. * * RTAS check-exception is called to collect data on the exception. If * the error is deemed recoverable, we log a warning and return. * For nonrecoverable errors, an error is logged and we stop all processing * as quickly as possible in order to prevent propagation of the failure. */ static irqreturn_t ras_error_interrupt(int irq, void *dev_id) { struct rtas_error_log *rtas_elog; int status; int fatal; spin_lock(&ras_log_buf_lock); status = rtas_call(ras_check_exception_token, 6, 1, NULL, RTAS_VECTOR_EXTERNAL_INTERRUPT, virq_to_hw(irq), RTAS_INTERNAL_ERROR, 1 /* Time Critical */, __pa(&ras_log_buf), rtas_get_error_log_max()); rtas_elog = (struct rtas_error_log *)ras_log_buf; if (status == 0 && rtas_error_severity(rtas_elog) >= RTAS_SEVERITY_ERROR_SYNC) fatal = 1; else fatal = 0; /* format and print the extended information */ log_error(ras_log_buf, ERR_TYPE_RTAS_LOG, fatal); if (fatal) { pr_emerg("Fatal hardware error reported by firmware"); pr_emerg("Check RTAS error log for details"); pr_emerg("Immediate power off"); emergency_sync(); kernel_power_off(); } else { pr_err("Recoverable hardware error reported by firmware"); } spin_unlock(&ras_log_buf_lock); return IRQ_HANDLED; }
void disk_emergency_sync(void) { struct super_block *sb; struct scsi_dev *sdev; /* host side sync... */ emergency_sync(); /* ...and now the disk side sync */ lock_kernel(); emergency_sync_scheduled = 0; for (sb = sb_entry(super_blocks.next); sb != sb_entry(&super_blocks); sb = sb_entry(sb->s_list.next)) { if (is_local_disk(sb->s_dev)){ if ((sdev = sb_to_scsidev(sb)) != NULL) ata_sync_platter(sdev); } } unlock_kernel(); printk(KERN_INFO "disk_emergency_sync done!\n"); }
static void sysrq_handle_sync(int key) { emergency_sync(); }
static void sysrq_handle_sync(int key, struct tty_struct *tty) { emergency_sync(); }
long gioctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct vm_area_struct *vma; #ifdef CONFIG_TIVO_DEVEL extern void sw_watchdog_threads_hold(void); extern void sw_watchdog_threads_release(void); #endif if (!arg) { printk(KERN_ERR "[gen_ioctl] Invalid arg\n"); return -EINVAL; } if (_IOC_TYPE(cmd) != GIOCTL_IOC_MAGIC) { printk(KERN_ERR "[gen_ioctl] cmd (0x%x) mismatch, " "called with 0x%x while expecting 0x%x\n", cmd, _IOC_TYPE(cmd), GIOCTL_IOC_MAGIC); return -EINVAL; } switch (cmd) { #ifdef CONFIG_TIVO_MOJAVE case GO_BIST: { extern void emergency_sync(void); extern void _machine_restart(void); extern unsigned long get_RAM_size(); unsigned long *p = (unsigned long *) (KSEG1+get_RAM_size()-PAGE_SIZE); /* * flush all disk buffers */ emergency_sync(); /*Disable Interrupts*/ local_irq_disable(); memset(p,0,PAGE_SIZE); *p++ = 0x42495354; /*BIST*/ *p++ = 1; /*Version*/ strcpy(p, arg); /*Boot Parameters*/ _machine_restart(); } #endif case CRASHALLASSRT: return tivocrashallassert(arg); #ifdef CONFIG_TICK_KILLER case TICK_KILLER: return tick_killer_start(arg); #endif case UPDATE_EXEC_CTX: /*Ineffective ioctl. Handling for the backward compatibility purposes. * Has be removed.*/ return 0; #ifdef CONFIG_KSTACK_GUARD case TEST_KSTACK_GUARD: test_kstack_guard_check(current); return 0; #endif case TEST_SGAT_DIO: { struct sgat_dio_fops gfops; sgat_dio_req dio_req; int c; int k = 'z'; struct scatterlist *p; sgat_dio_get_default_fops(&gfops); if (sgat_dio_init_req(&gfops, &dio_req, (sgat_dio_hdr_t *) arg)) { printk("Error: sgat_dio_init_req\n"); return -EINVAL; } if (sgat_dio_build_sg_list(&gfops, &dio_req, 1)) { printk("Error: sgat_dio_build_sg_list\n"); return -EINVAL; } p = (struct scatterlist *)dio_req.sclist; for (c = 0; c < dio_req.k_useg; c++) { memset(p->address, k, p->length); p++; } sgat_dio_exit_req(&gfops, &dio_req, 1); return 0; } #ifdef CONFIG_TIVO_SATA_HOTPLUG case SATA_UNPLUG_INT: { /* This is a blocking call */ int port, offset, regvalue; port = 1; /* Currently hard coding to port 1 */ if (port >= NUM_SATA_PORTS) return -EINVAL; /* SATA STATUS port */ offset = MMIO_SATA_STATUS + port * PORT_OFFSET; /* Check the status */ regvalue = mmio_inl(offset); regvalue &= PHY_IN_BIST; if (regvalue) return 0; /* If user request for non blocking */ if (arg & 0x2) { /* Any positive number is treated error output of command (not ioctl error). */ return 1; } /* Now we have to wait for interrupt */ //return sata_wait_for_IRQ(port, offset, PHY_IN_BIST); return 1; } case SATA_PLUG_INT: { /* This is a blocking call */ int port, offset, regvalue; port = 1; /* Currently hard coding to port 1 */ if (port >= NUM_SATA_PORTS) return -EINVAL; /* SATA STATUS port */ offset = MMIO_SATA_STATUS + port * PORT_OFFSET; /* Check the status */ regvalue = mmio_inl(offset); regvalue &= PHY_IS_RDY; if (regvalue) return 0; /* If user request for non blocking */ if (arg & 0x2) { /* Any positive number is treated error output of command (not ioctl error). */ return 1; } /* Now we have to wait for interrupt */ //return sata_wait_for_irq(port, offset, PHY_IS_RDY); return 1; } #endif case LOCKMEM: { printk("Pretending to LOCKMEM %p\n", (void *)arg); //struct iovec *iovec = (struct iovec *) arg; //if ( pindown_pages(NULL, iovec, 1, 1, WRITE) ) // return -EINVAL; return 0; } case UNLOCKMEM: { printk("Pretending to UNLOCKMEM %p\n", (void *)arg); // struct iovec *iovec = (struct iovec *) arg; // struct page **page_list; // struct page **pg_list; // unsigned int pg_addr; // int pgcount,pg; // pgcount = (((u_long)iovec->iov_base) + // iovec->iov_len + PAGE_SIZE - 1)/PAGE_SIZE - // ((u_long)iovec->iov_base)/PAGE_SIZE; // pg_addr = (unsigned int )(iovec->iov_base) & (~(PAGE_SIZE-1)); // page_list = kmalloc(sizeof(struct page **) * pgcount, GFP_KERNEL); // pg_list = page_list; // for ( pg = 0; pg < pgcount; pg++){ // *(pg_list++) = virt_to_page(pg_addr); // pg_addr += PAGE_SIZE; // } // unlock_pages(page_list); // kfree(*page_list); return 0; } case IS_PM_FWUPGD_REQD: { int ret = -EINVAL; #if SKIP_SATA_PM_FW_UPGD return -EACCES; #endif #ifdef CONFIG_TIVO_DEVEL /* Turn off sw watchdog for a while */ sw_watchdog_threads_hold(); #endif if (is_fw_upgd_reqd) ret = is_fw_upgd_reqd(); #ifdef CONFIG_TIVO_DEVEL sw_watchdog_threads_release(); #endif return ret; } case DWNLD_SATA_PM_FW: { int ret = -EINVAL; #if SKIP_SATA_PM_FW_UPGD return -EACCES; #endif #ifdef CONFIG_TIVO_DEVEL /* Turn off sw watchdog for a while until we complete * upgrading FW in blocking PIO mode */ sw_watchdog_threads_hold(); #endif if (upgd_fw_init) ret = upgd_fw_init(); #ifdef CONFIG_TIVO_DEVEL /*Trun on sw wdog */ sw_watchdog_threads_release(); #endif return ret; } case GET_VMA_INFO: { struct vma_info_struct s; copy_from_user(&s,(void *)arg,sizeof(s)); down_read(¤t->mm->mmap_sem); vma = find_vma(current->mm, s.address); if (!vma || vma->vm_start > s.address) { up_read(¤t->mm->mmap_sem); return -ENOMEM; } s.start = vma->vm_start; s.end = vma->vm_end-1; s.read = (vma->vm_flags & VM_READ)!=0; s.write = (vma->vm_flags & VM_WRITE)!=0; s.exec = (vma->vm_flags & VM_EXEC)!=0; s.shared = (vma->vm_flags & VM_SHARED)!=0; s.offset = vma->vm_pgoff*PAGE_SIZE; s.device=s.inode=0; if (vma->vm_file) { s.device=vma->vm_file->f_dentry->d_inode->i_rdev; s.inode=vma->vm_file->f_dentry->d_inode->i_ino; } up_read(¤t->mm->mmap_sem); copy_to_user((void *)arg, &s, sizeof(s)); return 0; } } // none of the above... printk(KERN_ERR "gen_ioctl: Invalid command (0x%x)\n",cmd); return -EINVAL; }