Exemplo n.º 1
0
void
xics_enable_irq(
	u_int	virq
	)
{
	u_int		irq;
	unsigned long	status;
	long	        call_status;

	virq -= XICS_IRQ_OFFSET;
	irq = virt_irq_to_real(virq);
	if (irq == XICS_IPI)
		return;
#ifdef CONFIG_IRQ_ALL_CPUS
	call_status = rtas_call(ibm_set_xive, 3, 1, (unsigned long*)&status,
				irq, smp_threads_ready ? default_distrib_server : default_server, DEFAULT_PRIORITY);
#else
	call_status = rtas_call(ibm_set_xive, 3, 1, (unsigned long*)&status,
				irq, default_server, DEFAULT_PRIORITY);
#endif
	if( call_status != 0 ) {
		printk("xics_enable_irq: irq=%x: rtas_call failed; retn=%lx, status=%lx\n",
		       irq, call_status, status);
		return;
	}
}
Exemplo n.º 2
0
/*
 * Handle power subsystem events (EPOW).
 *
 * Presently we just log the event has occurred.  This should be fixed
 * to examine the type of power failure and take appropriate action where
 * the time horizon permits something useful to be done.
 */
static irqreturn_t
ras_epow_interrupt(int irq, void *dev_id, struct pt_regs * regs)
{
	int status = 0xdeadbeef;
	int state = 0;
	int critical;

	status = rtas_call(ras_get_sensor_state_token, 2, 2, &state,
			   EPOW_SENSOR_TOKEN, EPOW_SENSOR_INDEX);

	if (state > 3)
		critical = 1;  /* Time Critical */
	else
		critical = 0;

	spin_lock(&ras_log_buf_lock);

	status = rtas_call(ras_check_exception_token, 6, 1, NULL,
			   RAS_VECTOR_OFFSET,
			   virt_irq_to_real(irq_offset_down(irq)),
			   RTAS_EPOW_WARNING | RTAS_POWERMGM_EVENTS,
			   critical, __pa(&ras_log_buf),
				rtas_get_error_log_max());

	udbg_printf("EPOW <0x%lx 0x%x 0x%x>\n",
		    *((unsigned long *)&ras_log_buf), status, state);
	printk(KERN_WARNING "EPOW <0x%lx 0x%x 0x%x>\n",
	       *((unsigned long *)&ras_log_buf), status, state);

	/* format and print the extended information */
	log_error(ras_log_buf, ERR_TYPE_RTAS_LOG, 0);

	spin_unlock(&ras_log_buf_lock);
	return IRQ_HANDLED;
}
Exemplo n.º 3
0
void
xics_end_irq(
	u_int	irq
	)
{
	int cpu = smp_processor_id();

	ops->cppr_info(cpu, 0); /* actually the value overwritten by ack */
	iosync();
	ops->xirr_info_set(cpu, ((0xff<<24) | (virt_irq_to_real(irq-XICS_IRQ_OFFSET))));
	iosync();
}
Exemplo n.º 4
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 pt_regs * regs)
{
	struct rtas_error_log *rtas_elog;
	int status = 0xdeadbeef;
	int fatal;

	spin_lock(&ras_log_buf_lock);

	status = rtas_call(ras_check_exception_token, 6, 1, NULL,
			   RAS_VECTOR_OFFSET,
			   virt_irq_to_real(irq_offset_down(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_elog->severity >= 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) {
		udbg_printf("Fatal HW Error <0x%lx 0x%x>\n",
			    *((unsigned long *)&ras_log_buf), status);
		printk(KERN_EMERG "Error: Fatal hardware error <0x%lx 0x%x>\n",
		       *((unsigned long *)&ras_log_buf), status);

#ifndef DEBUG
		/* Don't actually power off when debugging so we can test
		 * without actually failing while injecting errors.
		 * Error data will not be logged to syslog.
		 */
		ppc_md.power_off();
#endif
	} else {
		udbg_printf("Recoverable HW Error <0x%lx 0x%x>\n",
			    *((unsigned long *)&ras_log_buf), status);
		printk(KERN_WARNING
		       "Warning: Recoverable hardware error <0x%lx 0x%x>\n",
		       *((unsigned long *)&ras_log_buf), status);
	}

	spin_unlock(&ras_log_buf_lock);
	return IRQ_HANDLED;
}
Exemplo n.º 5
0
void
xics_disable_irq(
	u_int	virq
	)
{
	u_int		irq;
	unsigned long 	status;
	long 	        call_status;

	virq -= XICS_IRQ_OFFSET;
	irq = virt_irq_to_real(virq);
	call_status = rtas_call(ibm_int_off, 1, 1, (unsigned long*)&status, 
				irq);
	if( call_status != 0 ) {
		printk("xics_disable_irq: irq=%x: rtas_call failed, retn=%lx\n",
		       irq, call_status);
		return;
	}
}
Exemplo n.º 6
0
void xics_set_affinity(unsigned int virq, unsigned long cpumask)
{
        irq_desc_t *desc = irq_desc + virq;
	unsigned int irq;
	unsigned long flags;
	long status;
	unsigned long xics_status[2];
	u32 newmask;

	virq -= XICS_IRQ_OFFSET;
	irq = virt_irq_to_real(virq);
	if (irq == XICS_IPI)
		return;

        spin_lock_irqsave(&desc->lock, flags);

	status = rtas_call(ibm_get_xive, 1, 3, (void *)&xics_status, irq);

	if (status) {
		printk("xics_set_affinity: irq=%d ibm,get-xive returns %ld\n",
			irq, status);
		goto out;
	}

	/* For the moment only implement delivery to all cpus or one cpu */
	if (cpumask == 0xffffffff)
		newmask = default_distrib_server;
	else
		newmask = physmask(cpumask);

	status = rtas_call(ibm_set_xive, 3, 1, NULL,
				irq, newmask, xics_status[1]);

	if (status) {
		printk("xics_set_affinity irq=%d ibm,set-xive returns %ld\n",
			irq, status);
		goto out;
	}

out:
        spin_unlock_irqrestore(&desc->lock, flags);
}
Exemplo n.º 7
0
void
xics_enable_irq(
	u_int	virq
	)
{
	u_int		irq;
	unsigned long	status;
	long	        call_status;
	unsigned int    interrupt_server = default_server;

	virq -= XICS_IRQ_OFFSET;
	irq = virt_irq_to_real(virq);
	if (irq == XICS_IPI)
		return;

#ifdef CONFIG_IRQ_ALL_CPUS
	if((smp_num_cpus == systemcfg->processorCount) &&
	   (smp_threads_ready)) {
		interrupt_server = default_distrib_server;
	}
#endif
	call_status = rtas_call(ibm_set_xive, 3, 1, (unsigned long*)&status,
				irq, interrupt_server, DEFAULT_PRIORITY);

	if( call_status != 0 ) {
		printk("xics_enable_irq: irq=%x: rtas_call failed; retn=%lx, status=%lx\n",
		       irq, call_status, status);
		return;
	}
	/* Now unmask the interrupt (often a no-op) */
	call_status = rtas_call(ibm_int_on, 1, 1, (unsigned long*)&status, 
				irq);
	if( call_status != 0 ) {
		printk("xics_disable_irq on: irq=%x: rtas_call failed, retn=%lx\n",
		       irq, call_status);
		return;
	}
}