Пример #1
0
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;
}
Пример #2
0
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++;
}
Пример #3
0
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);
    }
}
Пример #4
0
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;
}
Пример #5
0
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();
}
Пример #6
0
/**
 * 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;
}
Пример #7
0
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;
}
Пример #8
0
/*
 * 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;
}
Пример #9
0
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");
}
Пример #10
0
static void sysrq_handle_sync(int key)
{
	emergency_sync();
}
Пример #11
0
static void sysrq_handle_sync(int key, struct tty_struct *tty)
{
    emergency_sync();
}
Пример #12
0
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(&current->mm->mmap_sem);
            vma = find_vma(current->mm, s.address);
            
            if (!vma || vma->vm_start > s.address)
            {
                up_read(&current->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(&current->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;
}