linux/arch/alpha/kernel/err_titan.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 *      linux/arch/alpha/kernel/err_titan.c
   4 *
   5 *      Copyright (C) 2000 Jeff Wiedemeier (Compaq Computer Corporation)
   6 *
   7 *      Error handling code supporting TITAN systems
   8 */
   9
  10#include <linux/init.h>
  11#include <linux/pci.h>
  12#include <linux/sched.h>
  13
  14#include <asm/io.h>
  15#include <asm/core_titan.h>
  16#include <asm/hwrpb.h>
  17#include <asm/smp.h>
  18#include <asm/err_common.h>
  19#include <asm/err_ev6.h>
  20#include <asm/irq_regs.h>
  21
  22#include "err_impl.h"
  23#include "proto.h"
  24
  25
  26static int
  27titan_parse_c_misc(u64 c_misc, int print)
  28{
  29#ifdef CONFIG_VERBOSE_MCHECK
  30        char *src;
  31        int nxs = 0;
  32#endif
  33        int status = MCHK_DISPOSITION_REPORT;
  34
  35#define TITAN__CCHIP_MISC__NXM          (1UL << 28)
  36#define TITAN__CCHIP_MISC__NXS__S       (29)
  37#define TITAN__CCHIP_MISC__NXS__M       (0x7)
  38
  39        if (!(c_misc & TITAN__CCHIP_MISC__NXM))
  40                return MCHK_DISPOSITION_UNKNOWN_ERROR;
  41
  42#ifdef CONFIG_VERBOSE_MCHECK
  43        if (!print)
  44                return status;
  45
  46        nxs = EXTRACT(c_misc, TITAN__CCHIP_MISC__NXS);
  47        switch(nxs) {
  48        case 0: /* CPU 0 */
  49        case 1: /* CPU 1 */
  50        case 2: /* CPU 2 */
  51        case 3: /* CPU 3 */
  52                src = "CPU";
  53                /* num is already the CPU number */
  54                break;
  55        case 4: /* Pchip 0 */
  56        case 5: /* Pchip 1 */
  57                src = "Pchip";
  58                nxs -= 4;
  59                break;
  60        default:/* reserved */
  61                src = "Unknown, NXS =";
  62                /* leave num untouched */
  63                break;
  64        }
  65
  66        printk("%s    Non-existent memory access from: %s %d\n", 
  67               err_print_prefix, src, nxs);
  68#endif /* CONFIG_VERBOSE_MCHECK */
  69
  70        return status;
  71}
  72
  73static int
  74titan_parse_p_serror(int which, u64 serror, int print)
  75{
  76        int status = MCHK_DISPOSITION_REPORT;
  77
  78#ifdef CONFIG_VERBOSE_MCHECK
  79        static const char * const serror_src[] = {
  80                "GPCI", "APCI", "AGP HP", "AGP LP"
  81        };
  82        static const char * const serror_cmd[] = {
  83                "DMA Read", "DMA RMW", "SGTE Read", "Reserved"
  84        };
  85#endif /* CONFIG_VERBOSE_MCHECK */
  86
  87#define TITAN__PCHIP_SERROR__LOST_UECC  (1UL << 0)
  88#define TITAN__PCHIP_SERROR__UECC       (1UL << 1)
  89#define TITAN__PCHIP_SERROR__CRE        (1UL << 2)
  90#define TITAN__PCHIP_SERROR__NXIO       (1UL << 3)
  91#define TITAN__PCHIP_SERROR__LOST_CRE   (1UL << 4)
  92#define TITAN__PCHIP_SERROR__ECCMASK    (TITAN__PCHIP_SERROR__UECC |      \
  93                                         TITAN__PCHIP_SERROR__CRE)
  94#define TITAN__PCHIP_SERROR__ERRMASK    (TITAN__PCHIP_SERROR__LOST_UECC | \
  95                                         TITAN__PCHIP_SERROR__UECC |      \
  96                                         TITAN__PCHIP_SERROR__CRE |       \
  97                                         TITAN__PCHIP_SERROR__NXIO |      \
  98                                         TITAN__PCHIP_SERROR__LOST_CRE)
  99#define TITAN__PCHIP_SERROR__SRC__S     (52)
 100#define TITAN__PCHIP_SERROR__SRC__M     (0x3)
 101#define TITAN__PCHIP_SERROR__CMD__S     (54)
 102#define TITAN__PCHIP_SERROR__CMD__M     (0x3)
 103#define TITAN__PCHIP_SERROR__SYN__S     (56)
 104#define TITAN__PCHIP_SERROR__SYN__M     (0xff)
 105#define TITAN__PCHIP_SERROR__ADDR__S    (15)
 106#define TITAN__PCHIP_SERROR__ADDR__M    (0xffffffffUL)
 107
 108        if (!(serror & TITAN__PCHIP_SERROR__ERRMASK))
 109                return MCHK_DISPOSITION_UNKNOWN_ERROR;
 110
 111#ifdef CONFIG_VERBOSE_MCHECK
 112        if (!print)
 113                return status;
 114
 115        printk("%s  PChip %d SERROR: %016llx\n",
 116               err_print_prefix, which, serror);
 117        if (serror & TITAN__PCHIP_SERROR__ECCMASK) {
 118                printk("%s    %sorrectable ECC Error:\n"
 119                       "      Source: %-6s  Command: %-8s  Syndrome: 0x%08x\n"
 120                       "      Address: 0x%llx\n",
 121                       err_print_prefix,
 122                       (serror & TITAN__PCHIP_SERROR__UECC) ? "Unc" : "C",
 123                       serror_src[EXTRACT(serror, TITAN__PCHIP_SERROR__SRC)],
 124                       serror_cmd[EXTRACT(serror, TITAN__PCHIP_SERROR__CMD)],
 125                       (unsigned)EXTRACT(serror, TITAN__PCHIP_SERROR__SYN),
 126                       EXTRACT(serror, TITAN__PCHIP_SERROR__ADDR));
 127        }
 128        if (serror & TITAN__PCHIP_SERROR__NXIO)
 129                printk("%s    Non Existent I/O Error\n", err_print_prefix);
 130        if (serror & TITAN__PCHIP_SERROR__LOST_UECC)
 131                printk("%s    Lost Uncorrectable ECC Error\n", 
 132                       err_print_prefix);
 133        if (serror & TITAN__PCHIP_SERROR__LOST_CRE)
 134                printk("%s    Lost Correctable ECC Error\n", err_print_prefix);
 135#endif /* CONFIG_VERBOSE_MCHECK */
 136
 137        return status;
 138}
 139
 140static int 
 141titan_parse_p_perror(int which, int port, u64 perror, int print)
 142{
 143        int cmd;
 144        unsigned long addr;
 145        int status = MCHK_DISPOSITION_REPORT;
 146
 147#ifdef CONFIG_VERBOSE_MCHECK
 148        static const char * const perror_cmd[] = {
 149                "Interrupt Acknowledge", "Special Cycle",
 150                "I/O Read",             "I/O Write",
 151                "Reserved",             "Reserved",
 152                "Memory Read",          "Memory Write",
 153                "Reserved",             "Reserved",
 154                "Configuration Read",   "Configuration Write",
 155                "Memory Read Multiple", "Dual Address Cycle",
 156                "Memory Read Line",     "Memory Write and Invalidate"
 157        };
 158#endif /* CONFIG_VERBOSE_MCHECK */
 159
 160#define TITAN__PCHIP_PERROR__LOST       (1UL << 0)
 161#define TITAN__PCHIP_PERROR__SERR       (1UL << 1)
 162#define TITAN__PCHIP_PERROR__PERR       (1UL << 2)
 163#define TITAN__PCHIP_PERROR__DCRTO      (1UL << 3)
 164#define TITAN__PCHIP_PERROR__SGE        (1UL << 4)
 165#define TITAN__PCHIP_PERROR__APE        (1UL << 5)
 166#define TITAN__PCHIP_PERROR__TA         (1UL << 6)
 167#define TITAN__PCHIP_PERROR__DPE        (1UL << 7)
 168#define TITAN__PCHIP_PERROR__NDS        (1UL << 8)
 169#define TITAN__PCHIP_PERROR__IPTPR      (1UL << 9)
 170#define TITAN__PCHIP_PERROR__IPTPW      (1UL << 10)
 171#define TITAN__PCHIP_PERROR__ERRMASK    (TITAN__PCHIP_PERROR__LOST |    \
 172                                         TITAN__PCHIP_PERROR__SERR |    \
 173                                         TITAN__PCHIP_PERROR__PERR |    \
 174                                         TITAN__PCHIP_PERROR__DCRTO |   \
 175                                         TITAN__PCHIP_PERROR__SGE |     \
 176                                         TITAN__PCHIP_PERROR__APE |     \
 177                                         TITAN__PCHIP_PERROR__TA |      \
 178                                         TITAN__PCHIP_PERROR__DPE |     \
 179                                         TITAN__PCHIP_PERROR__NDS |     \
 180                                         TITAN__PCHIP_PERROR__IPTPR |   \
 181                                         TITAN__PCHIP_PERROR__IPTPW)
 182#define TITAN__PCHIP_PERROR__DAC        (1UL << 47)
 183#define TITAN__PCHIP_PERROR__MWIN       (1UL << 48)
 184#define TITAN__PCHIP_PERROR__CMD__S     (52)
 185#define TITAN__PCHIP_PERROR__CMD__M     (0x0f)
 186#define TITAN__PCHIP_PERROR__ADDR__S    (14)
 187#define TITAN__PCHIP_PERROR__ADDR__M    (0x1fffffffful)
 188
 189        if (!(perror & TITAN__PCHIP_PERROR__ERRMASK))
 190                return MCHK_DISPOSITION_UNKNOWN_ERROR;
 191
 192        cmd = EXTRACT(perror, TITAN__PCHIP_PERROR__CMD);
 193        addr = EXTRACT(perror, TITAN__PCHIP_PERROR__ADDR) << 2;
 194
 195        /*
 196         * Initializing the BIOS on a video card on a bus without
 197         * a south bridge (subtractive decode agent) can result in 
 198         * master aborts as the BIOS probes the capabilities of the
 199         * card. XFree86 does such initialization. If the error
 200         * is a master abort (No DevSel as PCI Master) and the command
 201         * is an I/O read or write below the address where we start
 202         * assigning PCI I/O spaces (SRM uses 0x1000), then mark the
 203         * error as dismissable so starting XFree86 doesn't result
 204         * in a series of uncorrectable errors being reported. Also
 205         * dismiss master aborts to VGA frame buffer space
 206         * (0xA0000 - 0xC0000) and legacy BIOS space (0xC0000 - 0x100000)
 207         * for the same reason.
 208         *
 209         * Also mark the error dismissible if it looks like the right
 210         * error but only the Lost bit is set. Since the BIOS initialization
 211         * can cause multiple master aborts and the error interrupt can
 212         * be handled on a different CPU than the BIOS code is run on,
 213         * it is possible for a second master abort to occur between the
 214         * time the PALcode reads PERROR and the time it writes PERROR
 215         * to acknowledge the error. If this timing happens, a second
 216         * error will be signalled after the first, and if no additional
 217         * errors occur, will look like a Lost error with no additional 
 218         * errors on the same transaction as the previous error.
 219         */
 220        if (((perror & TITAN__PCHIP_PERROR__NDS) || 
 221             ((perror & TITAN__PCHIP_PERROR__ERRMASK) == 
 222              TITAN__PCHIP_PERROR__LOST)) &&
 223            ((((cmd & 0xE) == 2) && (addr < 0x1000)) ||
 224             (((cmd & 0xE) == 6) && (addr >= 0xA0000) && (addr < 0x100000)))) {
 225                status = MCHK_DISPOSITION_DISMISS;
 226        }
 227
 228#ifdef CONFIG_VERBOSE_MCHECK
 229        if (!print) 
 230                return status;
 231
 232        printk("%s  PChip %d %cPERROR: %016llx\n",
 233               err_print_prefix, which, 
 234               port ? 'A' : 'G', perror);
 235        if (perror & TITAN__PCHIP_PERROR__IPTPW)
 236                printk("%s    Invalid Peer-to-Peer Write\n", err_print_prefix);
 237        if (perror & TITAN__PCHIP_PERROR__IPTPR)
 238                printk("%s    Invalid Peer-to-Peer Read\n", err_print_prefix);
 239        if (perror & TITAN__PCHIP_PERROR__NDS)
 240                printk("%s    No DEVSEL as PCI Master [Master Abort]\n",
 241                       err_print_prefix);
 242        if (perror & TITAN__PCHIP_PERROR__DPE)
 243                printk("%s    Data Parity Error\n", err_print_prefix);
 244        if (perror & TITAN__PCHIP_PERROR__TA)
 245                printk("%s    Target Abort\n", err_print_prefix);
 246        if (perror & TITAN__PCHIP_PERROR__APE)
 247                printk("%s    Address Parity Error\n", err_print_prefix);
 248        if (perror & TITAN__PCHIP_PERROR__SGE)
 249                printk("%s    Scatter-Gather Error, Invalid PTE\n", 
 250                       err_print_prefix);
 251        if (perror & TITAN__PCHIP_PERROR__DCRTO)
 252                printk("%s    Delayed-Completion Retry Timeout\n", 
 253                       err_print_prefix);
 254        if (perror & TITAN__PCHIP_PERROR__PERR)
 255                printk("%s    PERR Asserted\n", err_print_prefix);
 256        if (perror & TITAN__PCHIP_PERROR__SERR)
 257                printk("%s    SERR Asserted\n", err_print_prefix);
 258        if (perror & TITAN__PCHIP_PERROR__LOST)
 259                printk("%s    Lost Error\n", err_print_prefix);
 260        printk("%s      Command: 0x%x - %s\n"
 261                 "      Address: 0x%lx\n",
 262               err_print_prefix,
 263               cmd, perror_cmd[cmd],
 264               addr);
 265        if (perror & TITAN__PCHIP_PERROR__DAC)
 266                printk("%s      Dual Address Cycle\n", err_print_prefix);
 267        if (perror & TITAN__PCHIP_PERROR__MWIN)
 268                printk("%s      Hit in Monster Window\n", err_print_prefix);
 269#endif /* CONFIG_VERBOSE_MCHECK */
 270
 271        return status;
 272}
 273
 274static int
 275titan_parse_p_agperror(int which, u64 agperror, int print)
 276{
 277        int status = MCHK_DISPOSITION_REPORT;
 278#ifdef CONFIG_VERBOSE_MCHECK
 279        int cmd, len;
 280        unsigned long addr;
 281
 282        static const char * const agperror_cmd[] = {
 283                "Read (low-priority)",  "Read (high-priority)",
 284                "Write (low-priority)", "Write (high-priority)",
 285                "Reserved",             "Reserved",
 286                "Flush",                "Fence"
 287        };
 288#endif /* CONFIG_VERBOSE_MCHECK */
 289
 290#define TITAN__PCHIP_AGPERROR__LOST     (1UL << 0)
 291#define TITAN__PCHIP_AGPERROR__LPQFULL  (1UL << 1)
 292#define TITAN__PCHIP_AGPERROR__HPQFULL  (1UL << 2)
 293#define TITAN__PCHIP_AGPERROR__RESCMD   (1UL << 3)
 294#define TITAN__PCHIP_AGPERROR__IPTE     (1UL << 4)
 295#define TITAN__PCHIP_AGPERROR__PTP      (1UL << 5)
 296#define TITAN__PCHIP_AGPERROR__NOWINDOW (1UL << 6)
 297#define TITAN__PCHIP_AGPERROR__ERRMASK  (TITAN__PCHIP_AGPERROR__LOST |    \
 298                                         TITAN__PCHIP_AGPERROR__LPQFULL | \
 299                                         TITAN__PCHIP_AGPERROR__HPQFULL | \
 300                                         TITAN__PCHIP_AGPERROR__RESCMD |  \
 301                                         TITAN__PCHIP_AGPERROR__IPTE |    \
 302                                         TITAN__PCHIP_AGPERROR__PTP |     \
 303                                         TITAN__PCHIP_AGPERROR__NOWINDOW)
 304#define TITAN__PCHIP_AGPERROR__DAC      (1UL << 48)
 305#define TITAN__PCHIP_AGPERROR__MWIN     (1UL << 49)
 306#define TITAN__PCHIP_AGPERROR__FENCE    (1UL << 59)
 307#define TITAN__PCHIP_AGPERROR__CMD__S   (50)
 308#define TITAN__PCHIP_AGPERROR__CMD__M   (0x07)
 309#define TITAN__PCHIP_AGPERROR__ADDR__S  (15)
 310#define TITAN__PCHIP_AGPERROR__ADDR__M  (0xffffffffUL)
 311#define TITAN__PCHIP_AGPERROR__LEN__S   (53)
 312#define TITAN__PCHIP_AGPERROR__LEN__M   (0x3f)
 313
 314        if (!(agperror & TITAN__PCHIP_AGPERROR__ERRMASK))
 315                return MCHK_DISPOSITION_UNKNOWN_ERROR;
 316
 317#ifdef CONFIG_VERBOSE_MCHECK
 318        if (!print)
 319                return status;
 320
 321        cmd = EXTRACT(agperror, TITAN__PCHIP_AGPERROR__CMD);
 322        addr = EXTRACT(agperror, TITAN__PCHIP_AGPERROR__ADDR) << 3;
 323        len = EXTRACT(agperror, TITAN__PCHIP_AGPERROR__LEN);
 324
 325        printk("%s  PChip %d AGPERROR: %016llx\n", err_print_prefix,
 326               which, agperror);
 327        if (agperror & TITAN__PCHIP_AGPERROR__NOWINDOW)
 328                printk("%s    No Window\n", err_print_prefix);
 329        if (agperror & TITAN__PCHIP_AGPERROR__PTP)
 330                printk("%s    Peer-to-Peer set\n", err_print_prefix);
 331        if (agperror & TITAN__PCHIP_AGPERROR__IPTE)
 332                printk("%s    Invalid PTE\n", err_print_prefix);
 333        if (agperror & TITAN__PCHIP_AGPERROR__RESCMD)
 334                printk("%s    Reserved Command\n", err_print_prefix);
 335        if (agperror & TITAN__PCHIP_AGPERROR__HPQFULL)
 336                printk("%s    HP Transaction Received while Queue Full\n", 
 337                       err_print_prefix);
 338        if (agperror & TITAN__PCHIP_AGPERROR__LPQFULL)
 339                printk("%s    LP Transaction Received while Queue Full\n", 
 340                       err_print_prefix);
 341        if (agperror & TITAN__PCHIP_AGPERROR__LOST)
 342                printk("%s    Lost Error\n", err_print_prefix);
 343        printk("%s      Command: 0x%x - %s, %d Quadwords%s\n"
 344                 "      Address: 0x%lx\n",
 345               err_print_prefix, cmd, agperror_cmd[cmd], len,
 346               (agperror & TITAN__PCHIP_AGPERROR__FENCE) ? ", FENCE" : "",
 347               addr);
 348        if (agperror & TITAN__PCHIP_AGPERROR__DAC)
 349                printk("%s      Dual Address Cycle\n", err_print_prefix);
 350        if (agperror & TITAN__PCHIP_AGPERROR__MWIN)
 351                printk("%s      Hit in Monster Window\n", err_print_prefix);
 352#endif /* CONFIG_VERBOSE_MCHECK */
 353
 354        return status;
 355}       
 356
 357static int
 358titan_parse_p_chip(int which, u64 serror, u64 gperror, 
 359                   u64 aperror, u64 agperror, int print)
 360{
 361        int status = MCHK_DISPOSITION_UNKNOWN_ERROR;
 362        status |= titan_parse_p_serror(which, serror, print);
 363        status |= titan_parse_p_perror(which, 0, gperror, print);
 364        status |= titan_parse_p_perror(which, 1, aperror, print);
 365        status |= titan_parse_p_agperror(which, agperror, print);
 366        return status;
 367}
 368
 369int
 370titan_process_logout_frame(struct el_common *mchk_header, int print)
 371{
 372        struct el_TITAN_sysdata_mcheck *tmchk =
 373                (struct el_TITAN_sysdata_mcheck *)
 374                ((unsigned long)mchk_header + mchk_header->sys_offset);
 375        int status = MCHK_DISPOSITION_UNKNOWN_ERROR;
 376
 377        status |= titan_parse_c_misc(tmchk->c_misc, print);
 378        status |= titan_parse_p_chip(0, tmchk->p0_serror, tmchk->p0_gperror,
 379                                     tmchk->p0_aperror, tmchk->p0_agperror, 
 380                                     print);
 381        status |= titan_parse_p_chip(1, tmchk->p1_serror, tmchk->p1_gperror,
 382                                     tmchk->p1_aperror, tmchk->p1_agperror, 
 383                                     print);
 384
 385        return status;
 386}
 387
 388void
 389titan_machine_check(unsigned long vector, unsigned long la_ptr)
 390{
 391        struct el_common *mchk_header = (struct el_common *)la_ptr;
 392        struct el_TITAN_sysdata_mcheck *tmchk =
 393                (struct el_TITAN_sysdata_mcheck *)
 394                ((unsigned long)mchk_header + mchk_header->sys_offset);
 395        u64 irqmask;
 396
 397        /*
 398         * Mask of Titan interrupt sources which are reported as machine checks
 399         *
 400         * 63 - CChip Error
 401         * 62 - PChip 0 H_Error
 402         * 61 - PChip 1 H_Error
 403         * 60 - PChip 0 C_Error
 404         * 59 - PChip 1 C_Error
 405         */
 406#define TITAN_MCHECK_INTERRUPT_MASK     0xF800000000000000UL
 407
 408        /*
 409         * Sync the processor
 410         */
 411        mb();
 412        draina();
 413        
 414        /*
 415         * Only handle system errors here 
 416         */
 417        if ((vector != SCB_Q_SYSMCHK) && (vector != SCB_Q_SYSERR)) {
 418                ev6_machine_check(vector, la_ptr);
 419                return;
 420        }
 421
 422        /* 
 423         * It's a system error, handle it here
 424         *
 425         * The PALcode has already cleared the error, so just parse it
 426         */
 427        
 428        /* 
 429         * Parse the logout frame without printing first. If the only error(s)
 430         * found are classified as "dismissable", then just dismiss them and
 431         * don't print any message
 432         */
 433        if (titan_process_logout_frame(mchk_header, 0) != 
 434            MCHK_DISPOSITION_DISMISS) {
 435                char *saved_err_prefix = err_print_prefix;
 436                err_print_prefix = KERN_CRIT;
 437
 438                /*
 439                 * Either a nondismissable error was detected or no
 440                 * recognized error was detected  in the logout frame 
 441                 * -- report the error in either case
 442                 */
 443                printk("%s"
 444                       "*System %s Error (Vector 0x%x) reported on CPU %d:\n", 
 445                       err_print_prefix,
 446                       (vector == SCB_Q_SYSERR)?"Correctable":"Uncorrectable",
 447                       (unsigned int)vector, (int)smp_processor_id());
 448                
 449#ifdef CONFIG_VERBOSE_MCHECK
 450                titan_process_logout_frame(mchk_header, alpha_verbose_mcheck);
 451                if (alpha_verbose_mcheck)
 452                        dik_show_regs(get_irq_regs(), NULL);
 453#endif /* CONFIG_VERBOSE_MCHECK */
 454
 455                err_print_prefix = saved_err_prefix;
 456
 457                /*
 458                 * Convert any pending interrupts which report as system
 459                 * machine checks to interrupts
 460                 */
 461                irqmask = tmchk->c_dirx & TITAN_MCHECK_INTERRUPT_MASK;
 462                titan_dispatch_irqs(irqmask);
 463        }       
 464
 465
 466        /* 
 467         * Release the logout frame 
 468         */
 469        wrmces(0x7);
 470        mb();
 471}
 472
 473/*
 474 * Subpacket Annotations
 475 */
 476static char *el_titan_pchip0_extended_annotation[] = {
 477        "Subpacket Header",     "P0_SCTL",      "P0_SERREN",
 478        "P0_APCTL",             "P0_APERREN",   "P0_AGPERREN",
 479        "P0_ASPRST",            "P0_AWSBA0",    "P0_AWSBA1",
 480        "P0_AWSBA2",            "P0_AWSBA3",    "P0_AWSM0",
 481        "P0_AWSM1",             "P0_AWSM2",     "P0_AWSM3",
 482        "P0_ATBA0",             "P0_ATBA1",     "P0_ATBA2",
 483        "P0_ATBA3",             "P0_GPCTL",     "P0_GPERREN",
 484        "P0_GSPRST",            "P0_GWSBA0",    "P0_GWSBA1",
 485        "P0_GWSBA2",            "P0_GWSBA3",    "P0_GWSM0",
 486        "P0_GWSM1",             "P0_GWSM2",     "P0_GWSM3",
 487        "P0_GTBA0",             "P0_GTBA1",     "P0_GTBA2",
 488        "P0_GTBA3",             NULL 
 489};
 490static char *el_titan_pchip1_extended_annotation[] = {
 491        "Subpacket Header",     "P1_SCTL",      "P1_SERREN",
 492        "P1_APCTL",             "P1_APERREN",   "P1_AGPERREN",
 493        "P1_ASPRST",            "P1_AWSBA0",    "P1_AWSBA1",
 494        "P1_AWSBA2",            "P1_AWSBA3",    "P1_AWSM0",
 495        "P1_AWSM1",             "P1_AWSM2",     "P1_AWSM3",
 496        "P1_ATBA0",             "P1_ATBA1",     "P1_ATBA2",
 497        "P1_ATBA3",             "P1_GPCTL",     "P1_GPERREN",
 498        "P1_GSPRST",            "P1_GWSBA0",    "P1_GWSBA1",
 499        "P1_GWSBA2",            "P1_GWSBA3",    "P1_GWSM0",
 500        "P1_GWSM1",             "P1_GWSM2",     "P1_GWSM3",
 501        "P1_GTBA0",             "P1_GTBA1",     "P1_GTBA2",
 502        "P1_GTBA3",             NULL 
 503};
 504static char *el_titan_memory_extended_annotation[] = {
 505        "Subpacket Header",     "AAR0",         "AAR1",
 506        "AAR2",                 "AAR3",         "P0_SCTL",
 507        "P0_GPCTL",             "P0_APCTL",     "P1_SCTL",
 508        "P1_GPCTL",             "P1_SCTL",      NULL 
 509};
 510
 511static struct el_subpacket_annotation el_titan_annotations[] = {
 512        SUBPACKET_ANNOTATION(EL_CLASS__REGATTA_FAMILY,
 513                             EL_TYPE__REGATTA__TITAN_PCHIP0_EXTENDED,
 514                             1,
 515                             "Titan PChip 0 Extended Frame",
 516                             el_titan_pchip0_extended_annotation),
 517        SUBPACKET_ANNOTATION(EL_CLASS__REGATTA_FAMILY,
 518                             EL_TYPE__REGATTA__TITAN_PCHIP1_EXTENDED,
 519                             1,
 520                             "Titan PChip 1 Extended Frame",
 521                             el_titan_pchip1_extended_annotation),
 522        SUBPACKET_ANNOTATION(EL_CLASS__REGATTA_FAMILY,
 523                             EL_TYPE__REGATTA__TITAN_MEMORY_EXTENDED,
 524                             1,
 525                             "Titan Memory Extended Frame",
 526                             el_titan_memory_extended_annotation),
 527        SUBPACKET_ANNOTATION(EL_CLASS__REGATTA_FAMILY,
 528                             EL_TYPE__TERMINATION__TERMINATION,
 529                             1,
 530                             "Termination Subpacket",
 531                             NULL)
 532};
 533
 534static struct el_subpacket *
 535el_process_regatta_subpacket(struct el_subpacket *header)
 536{
 537        if (header->class != EL_CLASS__REGATTA_FAMILY) {
 538                printk("%s  ** Unexpected header CLASS %d TYPE %d, aborting\n",
 539                       err_print_prefix,
 540                       header->class, header->type);
 541                return NULL;
 542        }
 543
 544        switch(header->type) {
 545        case EL_TYPE__REGATTA__PROCESSOR_ERROR_FRAME:
 546        case EL_TYPE__REGATTA__SYSTEM_ERROR_FRAME:
 547        case EL_TYPE__REGATTA__ENVIRONMENTAL_FRAME:
 548        case EL_TYPE__REGATTA__PROCESSOR_DBL_ERROR_HALT:
 549        case EL_TYPE__REGATTA__SYSTEM_DBL_ERROR_HALT:
 550                printk("%s  ** Occurred on CPU %d:\n", 
 551                       err_print_prefix,
 552                       (int)header->by_type.regatta_frame.cpuid);
 553                privateer_process_logout_frame((struct el_common *)
 554                        header->by_type.regatta_frame.data_start, 1);
 555                break;
 556        default:
 557                printk("%s  ** REGATTA TYPE %d SUBPACKET\n", 
 558                       err_print_prefix, header->type);
 559                el_annotate_subpacket(header);
 560                break;
 561        }
 562
 563
 564        return (struct el_subpacket *)((unsigned long)header + header->length);
 565} 
 566
 567static struct el_subpacket_handler titan_subpacket_handler = 
 568        SUBPACKET_HANDLER_INIT(EL_CLASS__REGATTA_FAMILY, 
 569                               el_process_regatta_subpacket);
 570
 571void __init
 572titan_register_error_handlers(void)
 573{
 574        size_t i;
 575
 576        for (i = 0; i < ARRAY_SIZE (el_titan_annotations); i++)
 577                cdl_register_subpacket_annotation(&el_titan_annotations[i]);
 578
 579        cdl_register_subpacket_handler(&titan_subpacket_handler);
 580
 581        ev6_register_error_handlers();
 582}
 583
 584
 585/*
 586 * Privateer
 587 */
 588
 589static int
 590privateer_process_680_frame(struct el_common *mchk_header, int print)
 591{
 592        int status = MCHK_DISPOSITION_UNKNOWN_ERROR;
 593#ifdef CONFIG_VERBOSE_MCHECK
 594        struct el_PRIVATEER_envdata_mcheck *emchk =
 595                (struct el_PRIVATEER_envdata_mcheck *)
 596                ((unsigned long)mchk_header + mchk_header->sys_offset);
 597
 598        /* TODO - categorize errors, for now, no error */
 599
 600        if (!print)
 601                return status;
 602
 603        /* TODO - decode instead of just dumping... */
 604        printk("%s  Summary Flags:         %016llx\n"
 605                 "  CChip DIRx:            %016llx\n"
 606                 "  System Management IR:  %016llx\n"
 607                 "  CPU IR:                %016llx\n"
 608                 "  Power Supply IR:       %016llx\n"
 609                 "  LM78 Fault Status:     %016llx\n"
 610                 "  System Doors:          %016llx\n"
 611                 "  Temperature Warning:   %016llx\n"
 612                 "  Fan Control:           %016llx\n"
 613                 "  Fatal Power Down Code: %016llx\n",
 614               err_print_prefix,
 615               emchk->summary,
 616               emchk->c_dirx,
 617               emchk->smir,
 618               emchk->cpuir,
 619               emchk->psir,
 620               emchk->fault,
 621               emchk->sys_doors,
 622               emchk->temp_warn,
 623               emchk->fan_ctrl,
 624               emchk->code);
 625#endif /* CONFIG_VERBOSE_MCHECK */
 626
 627        return status;
 628}
 629
 630int
 631privateer_process_logout_frame(struct el_common *mchk_header, int print)
 632{
 633        struct el_common_EV6_mcheck *ev6mchk = 
 634                (struct el_common_EV6_mcheck *)mchk_header;
 635        int status = MCHK_DISPOSITION_UNKNOWN_ERROR;
 636
 637        /*
 638         * Machine check codes
 639         */
 640#define PRIVATEER_MCHK__CORR_ECC                0x86    /* 630 */
 641#define PRIVATEER_MCHK__DC_TAG_PERR             0x9E    /* 630 */
 642#define PRIVATEER_MCHK__PAL_BUGCHECK            0x8E    /* 670 */
 643#define PRIVATEER_MCHK__OS_BUGCHECK             0x90    /* 670 */
 644#define PRIVATEER_MCHK__PROC_HRD_ERR            0x98    /* 670 */
 645#define PRIVATEER_MCHK__ISTREAM_CMOV_PRX        0xA0    /* 670 */
 646#define PRIVATEER_MCHK__ISTREAM_CMOV_FLT        0xA2    /* 670 */
 647#define PRIVATEER_MCHK__SYS_HRD_ERR             0x202   /* 660 */
 648#define PRIVATEER_MCHK__SYS_CORR_ERR            0x204   /* 620 */
 649#define PRIVATEER_MCHK__SYS_ENVIRON             0x206   /* 680 */
 650
 651        switch(ev6mchk->MCHK_Code) {
 652        /*
 653         * Vector 630 - Processor, Correctable
 654         */
 655        case PRIVATEER_MCHK__CORR_ECC:
 656        case PRIVATEER_MCHK__DC_TAG_PERR:
 657                /*
 658                 * Fall through to vector 670 for processing...
 659                 */
 660        /*
 661         * Vector 670 - Processor, Uncorrectable
 662         */
 663        case PRIVATEER_MCHK__PAL_BUGCHECK:
 664        case PRIVATEER_MCHK__OS_BUGCHECK:
 665        case PRIVATEER_MCHK__PROC_HRD_ERR:
 666        case PRIVATEER_MCHK__ISTREAM_CMOV_PRX:
 667        case PRIVATEER_MCHK__ISTREAM_CMOV_FLT:
 668                status |= ev6_process_logout_frame(mchk_header, print);
 669                break;
 670
 671        /*
 672         * Vector 620 - System, Correctable
 673         */
 674        case PRIVATEER_MCHK__SYS_CORR_ERR:
 675                /*
 676                 * Fall through to vector 660 for processing...
 677                 */
 678        /*
 679         * Vector 660 - System, Uncorrectable
 680         */
 681        case PRIVATEER_MCHK__SYS_HRD_ERR:
 682                status |= titan_process_logout_frame(mchk_header, print);
 683                break;
 684
 685        /* 
 686         * Vector 680 - System, Environmental
 687         */
 688        case PRIVATEER_MCHK__SYS_ENVIRON:       /* System, Environmental */
 689                status |= privateer_process_680_frame(mchk_header, print);
 690                break;
 691
 692        /* 
 693         * Unknown
 694         */
 695        default:
 696                status |= MCHK_DISPOSITION_REPORT;
 697                if (print) {
 698                        printk("%s** Unknown Error, frame follows\n", 
 699                               err_print_prefix);
 700                        mchk_dump_logout_frame(mchk_header);
 701                }
 702
 703        }
 704
 705        return status;
 706}
 707
 708void
 709privateer_machine_check(unsigned long vector, unsigned long la_ptr)
 710{
 711        struct el_common *mchk_header = (struct el_common *)la_ptr;
 712        struct el_TITAN_sysdata_mcheck *tmchk =
 713                (struct el_TITAN_sysdata_mcheck *)
 714                (la_ptr + mchk_header->sys_offset);
 715        u64 irqmask;
 716        char *saved_err_prefix = err_print_prefix;
 717
 718#define PRIVATEER_680_INTERRUPT_MASK            (0xE00UL)
 719#define PRIVATEER_HOTPLUG_INTERRUPT_MASK        (0xE00UL)
 720
 721        /*
 722         * Sync the processor.
 723         */
 724        mb();
 725        draina();
 726
 727        /* 
 728         * Only handle system events here.
 729         */
 730        if (vector != SCB_Q_SYSEVENT) 
 731                return titan_machine_check(vector, la_ptr);
 732
 733        /*
 734         * Report the event - System Events should be reported even if no
 735         * error is indicated since the event could indicate the return
 736         * to normal status.
 737         */
 738        err_print_prefix = KERN_CRIT;
 739        printk("%s*System Event (Vector 0x%x) reported on CPU %d:\n", 
 740               err_print_prefix,
 741               (unsigned int)vector, (int)smp_processor_id());
 742        privateer_process_680_frame(mchk_header, 1);
 743        err_print_prefix = saved_err_prefix;
 744        
 745        /* 
 746         * Convert any pending interrupts which report as 680 machine
 747         * checks to interrupts.
 748         */
 749        irqmask = tmchk->c_dirx & PRIVATEER_680_INTERRUPT_MASK;
 750
 751        /*
 752         * Dispatch the interrupt(s).
 753         */
 754        titan_dispatch_irqs(irqmask);
 755
 756        /* 
 757         * Release the logout frame.
 758         */
 759        wrmces(0x7);
 760        mb();
 761}
 762