All of lore.kernel.org
 help / color / mirror / Atom feed
From: Joshua Kinard <kumba@gentoo.org>
To: Linux MIPS List <linux-mips@linux-mips.org>
Subject: IP30: SMP Help
Date: Mon, 03 Nov 2014 00:54:05 -0500	[thread overview]
Message-ID: <5457187D.6030708@gentoo.org> (raw)

[-- Attachment #1: Type: text/plain, Size: 898 bytes --]


I've recently acquired a dual R14000 CPU for the Octane, so I am trying to get
SMP working again, but I can't get things setup properly.  I've attached both
ip30-irq.c and ip30-smp.c -- does anyone see any immediate problems (or just
where I am doing it wrong)?

Most reboot cycles with this code panics because init exited with a code of 0xa
or 0xb (which matches w/ SIGSEGV or SIGBUS).  Randomly, I can acquire a dash
shell by passing init=/bin/dash.  I can't do much in it, though.  A basic 'ls'
either segfaults or triggers a SIGBUS.  If I execute 'ls' enough times, it
eventually works.  Can't get much farther beyond that.

-- 
Joshua Kinard
Gentoo/MIPS
kumba@gentoo.org
4096R/D25D95E3 2011-03-28

"The past tempts us, the present confuses us, the future frightens us.  And our
lives slip away, moment by moment, lost in that vast, terrible in-between."

--Emperor Turhan, Centauri Republic

[-- Attachment #2: ip30-irq.c --]
[-- Type: text/plain, Size: 9125 bytes --]

/*
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file "COPYING" in the main directory of this archive
 * for more details.
 *
 * ip30-irq.c: Highlevel interrupt handling for IP30 architecture.
 *
 * Copyright (C) 2004-2007 Stanislaw Skowronek <skylark@linux-mips.org>
 *		 2009 Johannes Dickgreber <tanzy@gmx.de>
 *		 2007-2014 Joshua Kinard <kumba@gentoo.org>
 *
 * Inspired by ip27-irq.c and ip32-irq.c
 */

#include <linux/init.h>
#include <linux/irq.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/tick.h>

#include <asm/irq_cpu.h>
#include <asm/pci/bridge.h>

#include <asm/mach-ip30/heart.h>
#include <asm/mach-ip30/pcibr.h>
#include <asm/mach-ip30/racermp.h>
#include <asm/mach-ip30/addrs.h>

#undef DEBUG_IRQ

static DEFINE_SPINLOCK(heart_lock);
static int heart_irq_owner[NR_IRQS];
bridge_t *ip30_irq_to_bridge[NR_IRQS];
unsigned int ip30_irq_to_slot[NR_IRQS];

//extern void ip30_clockevent_broadcast(const int cpu);
//extern void ip30_clockevent_broadcast(const cpumask_t mask);

/* ----------------------------------------------------------------------- */

/**
 * ip30_do_error_irq - IRQ dispatch for all HEART error IRQs (51 - 63).
 */
static noinline void
ip30_do_error_irq(void)
{
	unsigned long errors;
	unsigned long cause;
	int i;

	irq_enter();
	errors = readq(HEART_ISR);
	cause = readq(HEART_CAUSE);
	writeq(HEART_INT_LEVEL4, HEART_CLR_ISR);

	/* Refer to ip30-heart.h for the HC_* macros to know what the cause was */
	if (cause > 0) {
		printk(KERN_WARNING "IP30: HEART ATTACK! ISR = 0x%.16llx "
		       "CAUSE = 0x%.16llx\n", (u64)(errors),(u64)(cause));

		/* i = 63; i >= 51; i-- */
		for (i = HEART_ERR_MASK_END; i >= HEART_ERR_MASK_START; i--)
			if ((errors >> i) & 1)
				printk(KERN_CONT "  HEART Error IRQ #%d\n", i);
	}
	irq_exit();
}

/**
 * ip30_do_heart_irq - IRQ dispatch for all HEART L0, L1, L2 IRQs (0 - 49).
 */
static noinline void
ip30_do_heart_irq(void)
{
	int irqnum = 49;
	int cpu = smp_processor_id();
	u64 heart_isr = readq(HEART_ISR);
	u64 heart_imr = readq(HEART_IMR(cpu));
	u64 irqs = (heart_isr &
	            (HEART_INT_LEVEL0 | HEART_INT_LEVEL1 | HEART_INT_LEVEL2) &
	            heart_imr);

#ifdef DEBUG_IRQ
	bridge_t *bvma = (bridge_t *)RAW_NODE_SWIN_BASE(0, 15);

	printk(KERN_INFO "IP30: received HEART IRQs: 0x%016llx "
	                 "(mask 0x%016llx) CPU%d BRIDGE %08x\n",
	                 heart_isr, heart_imr, cpu, bvma->b_int_status);
#endif

	/* Poll all IRQs in decreasing priority order */
	do {
		if (irqs & (1UL << irqnum))
			do_IRQ(irqnum);
		irqnum--;
	} while (likely(irqnum >= 0));
}

/* ----------------------------------------------------------------------- */

/**
 * plat_irq_dispatch - platform IRQ dispatch.
 */
asmlinkage void
plat_irq_dispatch(void)
{
	unsigned long pending;

	pending = (read_c0_cause() & read_c0_status() & ST0_IM);

	/* L5, CPU Counter/Compare */
	if (pending & CAUSEF_IP7)
		do_IRQ(MIPS_CPU_IRQ_BASE);
	/* L3, HEART Counter/Compare */
	else if (likely(pending & CAUSEF_IP5))
		do_IRQ(HEART_L3_INT_TIMER);
	/* L0-L2, HEART normal IRQs + IPI/SMP IRQs*/
	else if (likely(pending & (CAUSEF_IP2 | CAUSEF_IP3 | CAUSEF_IP4)))
		ip30_do_heart_irq();
	/* L4, HEART Errors */
	else if (unlikely(pending & CAUSEF_IP6))
		ip30_do_error_irq();
}

/* ----------------------------------------------------------------------- */



/* ----------------------------------------------------------------------- */
/* HEART IRQ Ops */

/**
 * startup_heart_irq - assigns a HEART IRQ to a CPU and/or Bridge slot.
 * @d: struct irq_data containing IRQ information.
 *
 * Returns 0 for now (XXX: this may need review, possible pending interrupts).
 */
static unsigned int
startup_heart_irq(struct irq_data *d)
{
	bridge_t *bridge;
	int cpu = smp_processor_id();
	u32 device, slot;
	u64 *imr;

	spin_lock(&heart_lock);

	if (heart_irq_owner[d->irq] != -1) {
		printk(KERN_ERR "DEBUG: startup_heart_irq: bad IRQ "
		       "startup request for IRQ %d on CPU %d "
		       "(already assigned to %d)!\n",
		       d->irq, cpu, heart_irq_owner[d->irq]);
		goto out;
	}

	/* store which CPU owns this IRQ */
	heart_irq_owner[d->irq] = cpu;

#ifdef DEBUG_IRQ
	printk(KERN_INFO "DEBUG: IP30: IRQ: startup_heart_irq: "
	       "IRQ %d on CPU %d!\n", d->irq, heart_irq_owner[d->irq]);
#endif

	/* clear IRQ flag */
	writeq(HEART_VEC_TO_IBIT(d->irq), HEART_CLR_ISR);

	/* unmask IRQ */
	imr = HEART_IMR(cpu);
	writeq(readq(imr) | HEART_VEC_TO_IBIT(d->irq), imr);

	/* Handle BRIDGE IRQs. */
	bridge = ip30_irq_to_bridge[d->irq];
	if (bridge) {
		slot = ip30_irq_to_slot[d->irq];
		bridge->b_int_enable |= (1 << slot);
		bridge->b_int_mode |= (1 << slot);
		device = bridge->b_int_device;
		device &= ~BRIDGE_INT_DEV_MASK(slot);
		device |=  BRIDGE_INT_DEV_SET(slot, slot);
		bridge->b_int_device = device;
		bridge->b_widget.w_tflush;
	}

out:
	spin_unlock(&heart_lock);

	/* XXX: This is probably not right; we could have pending irqs */
	return 0;
}

/**
 * shutdown_heart_irq - removes a HEART IRQ from a CPU and/or Bridge slot.
 * @d: struct irq_data containing IRQ information.
 */
static void
shutdown_heart_irq(struct irq_data *d)
{
	bridge_t *bridge;
	u64 *imr;

	spin_lock(&heart_lock);

	imr = HEART_IMR(heart_irq_owner[d->irq]);
	writeq(readq(imr) & ~(HEART_VEC_TO_IBIT(d->irq)), imr);

	bridge = ip30_irq_to_bridge[d->irq];
	if (bridge)
		bridge->b_int_enable &= ~(1UL << ip30_irq_to_slot[d->irq]);

	heart_irq_owner[d->irq] = -1;

	spin_unlock(&heart_lock);
}

/**
 * ack_heart_irq - acks a HEART IRQ.
 * @d: struct irq_data containing IRQ information.
 */
static void
ack_heart_irq(struct irq_data *d)
{

	spin_lock(&heart_lock);
	writeq(HEART_VEC_TO_IBIT(d->irq), HEART_CLR_ISR);
	spin_unlock(&heart_lock);
}

/**
 * mask_heart_irq - masks a HEART IRQ.
 * @d: struct irq_data containing IRQ information.
 */
static void
mask_heart_irq(struct irq_data *d)
{
	u64 *imr;

	spin_lock(&heart_lock);
	imr = HEART_IMR(heart_irq_owner[d->irq]);
	writeq(readq(imr) & ~(HEART_VEC_TO_IBIT(d->irq)), imr);
	spin_unlock(&heart_lock);
}

/**
 * mask_and_ack_heart_irq - masks and acks a HEART IRQ.
 * @d: struct irq_data containing IRQ information.
 */
static void
mask_and_ack_heart_irq(struct irq_data *d)
{
	u64 *imr;

	spin_lock(&heart_lock);
	writeq(HEART_VEC_TO_IBIT(d->irq), HEART_CLR_ISR);
	imr = HEART_IMR(heart_irq_owner[d->irq]);
	writeq(readq(imr) & ~(HEART_VEC_TO_IBIT(d->irq)), imr);
	spin_unlock(&heart_lock);
}

/**
 * unmask_heart_irq - unmasks a HEART IRQ.
 * @d: struct irq_data containing IRQ information.
 */
static void
unmask_heart_irq(struct irq_data *d)
{
	u64 *imr;

	spin_lock(&heart_lock);
	imr = HEART_IMR(heart_irq_owner[d->irq]);
	writeq(readq(imr) | HEART_VEC_TO_IBIT(d->irq), imr);
	spin_unlock(&heart_lock);
}

/**
 * struct ip30_heart_irq - HEART struct irq_chip ops.
 * @irq_startup: startup function.
 * @irq_shutdown: shutdown function.
 * @irq_ack: ack function.
 * @irq_mask: mask function.
 * @irq_mask_ack: mask & ack function.
 * @irq_unmask: unmask function.
 */
static struct
irq_chip ip30_heart_irq = {
	.name = "HEART",
	.irq_startup = startup_heart_irq,
	.irq_shutdown = shutdown_heart_irq,
	.irq_ack = ack_heart_irq,
	.irq_mask = mask_heart_irq,
	.irq_mask_ack = mask_and_ack_heart_irq,
	.irq_unmask = unmask_heart_irq,
};
/* ----------------------------------------------------------------------- */

static inline void ip30_unmask_boot_cpu_irq(struct irq_data *d)
{
	set_c0_status(0x100 << (d->irq - MIPS_CPU_IRQ_BASE));
}

static inline void ip30_mask_boot_cpu_irq(struct irq_data *d)
{
	clear_c0_status(0x100 << (d->irq - MIPS_CPU_IRQ_BASE));
}

static struct irq_chip ip30_boot_cpu_irq_controller = {
	.name		= "IP30-CPU0-IRQ",
	.irq_ack	= ip30_mask_boot_cpu_irq,
	.irq_mask	= ip30_mask_boot_cpu_irq,
	.irq_mask_ack	= ip30_mask_boot_cpu_irq,
	.irq_unmask	= ip30_unmask_boot_cpu_irq,
	.irq_eoi	= ip30_unmask_boot_cpu_irq,
};

/* ----------------------------------------------------------------------- */
/* Arch IRQ initialization - runs on CPU0 only. */

/**
 * arch_init_irq - arch initialization function.
 */
void __init
arch_init_irq(void)
{
	int irq;

	/* Ack everything */
	writeq(HEART_ACK_ALL_MASK, HEART_CLR_ISR);

	/* Mask all IRQs */
	writeq(HEART_CLR_ALL_MASK, HEART_IMR(0));
	writeq(HEART_CLR_ALL_MASK, HEART_IMR(1));
	writeq(HEART_CLR_ALL_MASK, HEART_IMR(2));
	writeq(HEART_CLR_ALL_MASK, HEART_IMR(3));

	/* Leave HEART errors enabled */
	writeq(HEART_BR_ERR_MASK, HEART_IMR(0));

	for (irq = HEART_IRQ_BASE; irq < HEART_IRQS; irq++) {
		heart_irq_owner[irq] = -1;
		irq_set_chip_and_handler(irq, &ip30_heart_irq, handle_level_irq);
	}

	/* Init CPU0 IRQs */
//	mips_cpu_irq_init();
	irq_set_chip_and_handler(MIPS_CPU_IRQ_BASE,
				 &ip30_boot_cpu_irq_controller,
				 handle_percpu_irq);
	change_c0_status(ST0_IM, (STATUSF_IP2 | STATUSF_IP3 | STATUSF_IP4 |
	                          STATUSF_IP5 | STATUSF_IP6 | STATUSF_IP7));

	printk(KERN_INFO "IP30: HEART interrupt controller initialized.\n");
}
/* ----------------------------------------------------------------------- */

[-- Attachment #3: ip30-smp.c --]
[-- Type: text/plain, Size: 7600 bytes --]

/*
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file "COPYING" in the main directory of this archive
 * for more details.
 *
 * ip30-smp.c: SMP on IP30 architecture.
 *
 * Copyright (C) 2005-2007 Stanislaw Skowronek <skylark@linux-mips.org>
 *               2006-2007 Joshua Kinard <kumba@gentoo.org>
 *               2009 Johannes Dickgreber <tanzy@gmx.de>
 */

#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/tick.h>
#include <linux/spinlock_types.h>

#include <asm/time.h>
#include <asm/cacheflush.h>

#include <asm/mach-ip30/heart.h>
#include <asm/mach-ip30/racermp.h>

static DEFINE_SPINLOCK(ip30_ipi_lock);
//static DEFINE_SPINLOCK(ip30_timer_lock);
static DEFINE_PER_CPU(int, ip30_ipi_action_mask);
static DEFINE_PER_CPU(char[15], ip30_ipi_name);
//static DEFINE_PER_CPU(char[17], ip30_timer_name);

//void ip30_clockevent_broadcast(const int cpu)
//{
//#ifdef CONFIG_SMP
//	/* There can only ever be 2 CPUs in an Octane, so keep it simple. */
//#endif
//}

/* ----------------------------------------------------------------------- */
/* SMP IPI Ops */

/* Runs on CPUx and sends an IPI to CPUy. */
static void ip30_send_ipi_single(int cpu, unsigned int action)
{
//	unsigned long flags;

//	printk(KERN_INFO "DEBUG: IP30: SMP: ip30_send_ipi_single CPU%d -> CPU%d: action: 0x%.8x\n", smp_processor_id(), cpu, action);
//	spin_lock_irqsave(&ip30_ipi_lock, flags);
	spin_lock(&ip30_ipi_lock);
	per_cpu(ip30_ipi_action_mask, cpu) |= action;
	writeq(HEART_VEC_TO_IBIT(HEART_L2_INT_IPI_CPU(cpu)), HEART_SET_ISR);
	spin_unlock(&ip30_ipi_lock);
//	spin_unlock_irqrestore(&ip30_ipi_lock, flags);
}

/* IRQ handler that runs on CPUy and services the IPI. */
static irqreturn_t ip30_ipi_irq(int irq, void *dev_id)
{
	int action;
	int cpu = smp_processor_id();
//	unsigned long flags;

//	spin_lock_irqsave(&ip30_ipi_lock, flags);
	spin_lock(&ip30_ipi_lock);
	action = __get_cpu_var(ip30_ipi_action_mask);
	per_cpu(ip30_ipi_action_mask, cpu) = 0;
	writeq(HEART_VEC_TO_IBIT(HEART_L2_INT_IPI_CPU(cpu)), HEART_CLR_ISR);
	spin_unlock(&ip30_ipi_lock);
//	spin_unlock_irqrestore(&ip30_ipi_lock, flags);

//	printk(KERN_INFO "DEBUG: IP30: SMP: ip30_ipi_irq: cpu%d: action: 0x%.8x\n", cpu, action);

	if (action & SMP_RESCHEDULE_YOURSELF)
		scheduler_ipi();

	if (action & SMP_CALL_FUNCTION)
		smp_call_function_interrupt();

	return IRQ_HANDLED;
}

///* IRQ handler that runs on CPUy and services the CPU Timer. */
//static irqreturn_t ip30_timer_irq(int irq, void *dev_id)
//{
//	int cpu = smp_processor_id();
//	struct clock_event_device *cd;
//
//	spin_lock(&ip30_timer_lock);
//	cd = tick_get_device(cpu)->evtdev;
//	cd->event_handler(cd);
////	printk(KERN_INFO "DEBUG: IP30: SMP: ip30_timer_irq: CPU%d: %s\n", cpu, cd->name);
//	spin_unlock(&ip30_timer_lock);
//	writeq(HEART_VEC_TO_IBIT(HEART_L2_INT_TIMER_CPU(cpu)), HEART_CLR_ISR);
//
//	return IRQ_HANDLED;
//}

static void ip30_send_ipi_mask(const struct cpumask *mask, unsigned int action)
{
	u32 i;

	for_each_cpu(i, mask)
		ip30_send_ipi_single(i, action);
}

static void __init ip30_smp_setup(void)
{
	int i;
	int ncpu = 0;
	int vcpu;

	for (i = 0; i < NR_CPUS; i++) {
		if (readl(MP_MAGIC(i)) == MPCONF_MAGIC) {
			vcpu = readl(MP_VIRTID(i));
			__cpu_number_map[i] = vcpu;
			__cpu_logical_map[vcpu] = i;
			set_cpu_possible(i, true);
			set_cpu_present(i, true);
			printk(KERN_INFO "IP30: Slot: %d, PrID: %.8x, PhyID: %d, VirtID: %d\n",
			       i, readl(MP_PRID(i)), readl(MP_PHYSID(i)), vcpu);
			ncpu++;
		}
	}
	printk(KERN_INFO "IP30: Detected %d CPU(s) present.\n", ncpu);
}

/* Runs on CPU0 */
static void __init ip30_prepare_cpus(unsigned int max_cpus)
{
	int cpu = smp_processor_id();
	unsigned char *ipi_name = per_cpu(ip30_ipi_name, cpu);
//	unsigned char *timer_name = per_cpu(ip30_timer_name, cpu);

	printk(KERN_INFO "DEBUG: IP30: SMP: ip30_prepare_cpus\n");

	/* Request an IRQ number for CPU0 IPI. */
	snprintf(ipi_name, 15, "ip30-cpu%d-ipi", cpu);
	if (request_irq(HEART_L2_INT_IPI_CPU(cpu), ip30_ipi_irq, IRQF_PERCPU,
	                ipi_name, NULL))
		panic("Can't request CPU%d IPI interrupt", cpu);

//	snprintf(timer_name, 17, "ip30-cpu%d-timer", cpu);
//	if (request_irq(HEART_L2_INT_TIMER_CPU(cpu), ip30_timer_irq, IRQF_PERCPU,
//	                timer_name, NULL))
//		panic("Can't request CPU%d Broadcast Timer interrupt", cpu);

	/* Enable the IPI interrupt on CPU0 IP4. */
//	change_c0_status(ST0_IM, STATUSF_IP4);
}

/* Runs on CPU0 and boots CPUx, where x > 0 */
static void ip30_boot_secondary(int cpu, struct task_struct *idle)
{
	int boot_cpu = smp_processor_id();
//	struct thread_info *gp = task_thread_info(idle);

	printk(KERN_INFO "DEBUG: IP30: SMP: ip30_boot_secondary: CPU%d -> CPU%d\n", boot_cpu, cpu);

	/* Stack pointer (sp). */
	writeq(__KSTK_TOS(idle), MP_STACKADDR(cpu));

	/* Global pointer (gp). */
	writeq((unsigned long)task_thread_info(idle), MP_LPARM(cpu));
//	writeq((unsigned long)gp, MP_LPARM(cpu));

	/* XXX: I don't know if this is needed or not.  Copied from elsewhere. */
//	flush_icache_range((unsigned long)gp,
//	                   (unsigned long)(gp + sizeof(struct thread_info)));

	/* Boot CPU1. */
	writeq((unsigned long)ip30_smp_bootstrap, MP_LAUNCH(cpu));
//	mb();

	/* XXX: This is needed to "kick" the CPU awake.  Bug? */
	pr_info("SMP: Booting CPU%d...\n", cpu);
}

/* Runs on CPUx, where x > 0 */
static void ip30_init_secondary(void)
{
	int cpu = smp_processor_id();

	printk(KERN_INFO "DEBUG: IP30: SMP: ip30_init_secondary on CPU%d\n", cpu);

}

static inline void ip30_unmask_2nd_cpu_irq(struct irq_data *d)
{
	set_c0_status(0x100 << (d->irq - (MIPS_CPU_IRQ_BASE + 1)));
}

static inline void ip30_mask_2nd_cpu_irq(struct irq_data *d)
{
	clear_c0_status(0x100 << (d->irq - (MIPS_CPU_IRQ_BASE + 1)));
}

static struct irq_chip ip30_2nd_cpu_irq_controller = {
	.name		= "IP30-CPU1-IRQ",
	.irq_ack	= ip30_mask_2nd_cpu_irq,
	.irq_mask	= ip30_mask_2nd_cpu_irq,
	.irq_mask_ack	= ip30_mask_2nd_cpu_irq,
	.irq_unmask	= ip30_unmask_2nd_cpu_irq,
	.irq_eoi	= ip30_unmask_2nd_cpu_irq,
};

static void ip30_smp_finish(void)
{
	int cpu = smp_processor_id();
	unsigned char *ipi_name = per_cpu(ip30_ipi_name, cpu);
//	unsigned char *timer_name = per_cpu(ip30_timer_name, cpu);

	printk(KERN_INFO "DEBUG: IP30: SMP: ip30_smp_finish: CPU%d\n", cpu);

	irq_set_chip_and_handler((MIPS_CPU_IRQ_BASE + 1),
				 &ip30_2nd_cpu_irq_controller,
				 handle_percpu_irq);
//	write_c0_compare(read_c0_count() + mips_hpt_frequency / HZ);
	change_c0_status(ST0_IM, (STATUSF_IP2 | STATUSF_IP3 | STATUSF_IP4 |
	                          STATUSF_IP5 | STATUSF_IP6 | STATUSF_IP7));
	local_irq_enable();

	/* Request an IRQ number for CPU1 IPI. */
	snprintf(ipi_name, 15, "ip30-cpu%d-ipi", cpu);
	if (request_irq(HEART_L2_INT_IPI_CPU(cpu), ip30_ipi_irq, IRQF_PERCPU,
	                ipi_name, NULL))
		panic("Can't request CPU%d IPI interrupt", cpu);

//	snprintf(timer_name, 17, "ip30-cpu%d-timer", cpu);
//	if (request_irq(HEART_L2_INT_TIMER_CPU(cpu), ip30_timer_irq, IRQF_PERCPU,
//	                timer_name, NULL))
//		panic("Can't request CPU%d Broadcast Timer interrupt", cpu);

	pr_info("SMP: CPU%d is running\n", smp_processor_id());
}

struct plat_smp_ops ip30_smp_ops = {
	.send_ipi_single	= ip30_send_ipi_single,
	.send_ipi_mask		= ip30_send_ipi_mask,
	.init_secondary		= ip30_init_secondary,
	.smp_finish		= ip30_smp_finish,
	.boot_secondary		= ip30_boot_secondary,
	.smp_setup		= ip30_smp_setup,
	.prepare_cpus		= ip30_prepare_cpus,
};

             reply	other threads:[~2014-11-03  5:54 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-11-03  5:54 Joshua Kinard [this message]
2014-11-10  8:17 ` IP30: SMP Help Joshua Kinard
2014-11-18  9:30   ` Joshua Kinard
2014-11-18 10:05     ` Maciej W. Rozycki
2014-11-18 12:37       ` Joshua Kinard
2014-11-18 13:10         ` Maciej W. Rozycki
2014-11-19 10:59           ` Joshua Kinard
2014-11-19 12:06             ` Maciej W. Rozycki
2014-11-19 15:22               ` Ralf Baechle
2014-11-21  6:13                 ` Joshua Kinard

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=5457187D.6030708@gentoo.org \
    --to=kumba@gentoo.org \
    --cc=linux-mips@linux-mips.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.