arch/powerpc/platforms/powermac/smp.c

Source file repositories/reference/linux-study-clean/arch/powerpc/platforms/powermac/smp.c

File Facts

System
Linux kernel
Corpus path
arch/powerpc/platforms/powermac/smp.c
Extension
.c
Size
25145 bytes
Lines
1028
Domain
Architecture Layer
Bucket
arch/powerpc
Inferred role
Architecture Layer: implementation source
Status
source implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

switch(psurge_type) {
		case PSURGE_DUAL:
			out_8(psurge_sec_intr, ~0);
			break;
		case PSURGE_NONE:
			break;
		default:
			PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_CLR, 1 << cpu);
		}
	}
}

/*
 * On powersurge (old SMP powermac architecture) we don't have
 * separate IPIs for separate messages like openpic does.  Instead
 * use the generic demux helpers
 *  -- paulus.
 */
static irqreturn_t psurge_ipi_intr(int irq, void *d)
{
	psurge_clr_ipi(smp_processor_id());
	smp_ipi_demux();

	return IRQ_HANDLED;
}

static void smp_psurge_cause_ipi(int cpu)
{
	psurge_set_ipi(cpu);
}

static int psurge_host_map(struct irq_domain *h, unsigned int virq,
			 irq_hw_number_t hw)
{
	irq_set_chip_and_handler(virq, &dummy_irq_chip, handle_percpu_irq);

	return 0;
}

static const struct irq_domain_ops psurge_host_ops = {
	.map	= psurge_host_map,
};

static int __init psurge_secondary_ipi_init(void)
{
	int rc = -ENOMEM;

	psurge_host = irq_domain_create_nomap(NULL, ~0, &psurge_host_ops, NULL);

	if (psurge_host)
		psurge_secondary_virq = irq_create_direct_mapping(psurge_host);

	if (psurge_secondary_virq)
		rc = request_irq(psurge_secondary_virq, psurge_ipi_intr,
			IRQF_PERCPU | IRQF_NO_THREAD, "IPI", NULL);

	if (rc)
		pr_err("Failed to setup secondary cpu IPI\n");

	return rc;
}

/*
 * Determine a quad card presence. We read the board ID register, we
 * force the data bus to change to something else, and we read it again.
 * It it's stable, then the register probably exist (ugh !)
 */
static int __init psurge_quad_probe(void)
{
	int type;
	unsigned int i;

	type = PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID);
	if (type < PSURGE_QUAD_OKEE || type > PSURGE_QUAD_ICEGRASS
	    || type != PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID))
		return PSURGE_DUAL;

	/* looks OK, try a slightly more rigorous test */
	/* bogus is not necessarily cacheline-aligned,
	   though I don't suppose that really matters.  -- paulus */
	for (i = 0; i < 100; i++) {
		volatile u32 bogus[8];
		bogus[(0+i)%8] = 0x00000000;
		bogus[(1+i)%8] = 0x55555555;
		bogus[(2+i)%8] = 0xFFFFFFFF;
		bogus[(3+i)%8] = 0xAAAAAAAA;
		bogus[(4+i)%8] = 0x33333333;
		bogus[(5+i)%8] = 0xCCCCCCCC;
		bogus[(6+i)%8] = 0xCCCCCCCC;
		bogus[(7+i)%8] = 0x33333333;

Annotation

Implementation Notes