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