arch/mips/dec/kn02xa-berr.c

Source file repositories/reference/linux-study-clean/arch/mips/dec/kn02xa-berr.c

File Facts

System
Linux kernel
Corpus path
arch/mips/dec/kn02xa-berr.c
Extension
.c
Size
3898 bytes
Lines
142
Domain
Architecture Layer
Bucket
arch/mips
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

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 *	Bus error event handling code for 5000-series systems equipped
 *	with parity error detection logic, i.e. DECstation/DECsystem
 *	5000/120, /125, /133 (KN02-BA), 5000/150 (KN04-BA) and Personal
 *	DECstation/DECsystem 5000/20, /25, /33 (KN02-CA), 5000/50
 *	(KN04-CA) systems.
 *
 *	Copyright (c) 2005, 2026  Maciej W. Rozycki
 */

#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/ratelimit.h>
#include <linux/types.h>

#include <asm/addrspace.h>
#include <asm/cpu-type.h>
#include <asm/irq_regs.h>
#include <asm/ptrace.h>
#include <asm/traps.h>

#include <asm/dec/kn02ca.h>
#include <asm/dec/kn02xa.h>
#include <asm/dec/kn05.h>

static inline void dec_kn02xa_be_ack(void)
{
	volatile u32 *mer = (void *)CKSEG1ADDR(KN02XA_MER);
	volatile u32 *mem_intr = (void *)CKSEG1ADDR(KN02XA_MEM_INTR);

	*mer = KN02CA_MER_INTR;		/* Clear errors; keep the ARC IRQ. */
	*mem_intr = 0;			/* Any write clears the bus IRQ. */
	iob();
}

static int dec_kn02xa_be_backend(struct pt_regs *regs, int is_fixup,
				 int invoker)
{
	volatile u32 *kn02xa_mer = (void *)CKSEG1ADDR(KN02XA_MER);
	volatile u32 *kn02xa_ear = (void *)CKSEG1ADDR(KN02XA_EAR);

	static const char excstr[] = "exception";
	static const char intstr[] = "interrupt";
	static const char cpustr[] = "CPU";
	static const char mreadstr[] = "memory read";
	static const char readstr[] = "read";
	static const char writestr[] = "write";
	static const char timestr[] = "timeout";
	static const char paritystr[] = "parity error";
	static const char lanestat[][4] = { " OK", "BAD" };

	static DEFINE_RATELIMIT_STATE(rs,
				      DEFAULT_RATELIMIT_INTERVAL,
				      DEFAULT_RATELIMIT_BURST);

	const char *kind, *agent, *cycle, *event;
	unsigned long address;

	u32 mer = *kn02xa_mer;
	u32 ear = *kn02xa_ear;
	int action = MIPS_BE_FATAL;

	/* Ack ASAP, so that any subsequent errors get caught. */
	dec_kn02xa_be_ack();

	kind = invoker ? intstr : excstr;

	/* No DMA errors? */
	agent = cpustr;

	address = ear & KN02XA_EAR_ADDRESS;

	/* Low 256MB is decoded as memory, high -- as TC. */
	if (address < 0x10000000) {
		cycle = mreadstr;
		event = paritystr;
	} else {
		cycle = invoker ? writestr : readstr;
		event = timestr;
	}

	if (is_fixup)
		action = MIPS_BE_FIXUP;

	if (action != MIPS_BE_FIXUP && __ratelimit(&rs)) {
		printk(KERN_ALERT "Bus error %s: %s %s %s at %#010lx\n",
			kind, agent, cycle, event, address);

Annotation

Implementation Notes