ia64/linux-2.6.18-xen.hg

annotate arch/alpha/kernel/core_lca.c @ 897:329ea0ccb344

balloon: try harder to balloon up under memory pressure.

Currently if the balloon driver is unable to increase the guest's
reservation it assumes the failure was due to reaching its full
allocation, gives up on the ballooning operation and records the limit
it reached as the "hard limit". The driver will not try again until
the target is set again (even to the same value).

However it is possible that ballooning has in fact failed due to
memory pressure in the host and therefore it is desirable to keep
attempting to reach the target in case memory becomes available. The
most likely scenario is that some guests are ballooning down while
others are ballooning up and therefore there is temporary memory
pressure while things stabilise. You would not expect a well behaved
toolstack to ask a domain to balloon to more than its allocation nor
would you expect it to deliberately over-commit memory by setting
balloon targets which exceed the total host memory.

This patch drops the concept of a hard limit and causes the balloon
driver to retry increasing the reservation on a timer in the same
manner as when decreasing the reservation.

Also if we partially succeed in increasing the reservation
(i.e. receive less pages than we asked for) then we may as well keep
those pages rather than returning them to Xen.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Jun 05 14:01:20 2009 +0100 (2009-06-05)
parents 831230e53067
children
rev   line source
ian@0 1 /*
ian@0 2 * linux/arch/alpha/kernel/core_lca.c
ian@0 3 *
ian@0 4 * Written by David Mosberger (davidm@cs.arizona.edu) with some code
ian@0 5 * taken from Dave Rusling's (david.rusling@reo.mts.dec.com) 32-bit
ian@0 6 * bios code.
ian@0 7 *
ian@0 8 * Code common to all LCA core logic chips.
ian@0 9 */
ian@0 10
ian@0 11 #define __EXTERN_INLINE inline
ian@0 12 #include <asm/io.h>
ian@0 13 #include <asm/core_lca.h>
ian@0 14 #undef __EXTERN_INLINE
ian@0 15
ian@0 16 #include <linux/types.h>
ian@0 17 #include <linux/pci.h>
ian@0 18 #include <linux/init.h>
ian@0 19 #include <linux/tty.h>
ian@0 20
ian@0 21 #include <asm/ptrace.h>
ian@0 22 #include <asm/smp.h>
ian@0 23
ian@0 24 #include "proto.h"
ian@0 25 #include "pci_impl.h"
ian@0 26
ian@0 27
ian@0 28 /*
ian@0 29 * BIOS32-style PCI interface:
ian@0 30 */
ian@0 31
ian@0 32 /*
ian@0 33 * Machine check reasons. Defined according to PALcode sources
ian@0 34 * (osf.h and platform.h).
ian@0 35 */
ian@0 36 #define MCHK_K_TPERR 0x0080
ian@0 37 #define MCHK_K_TCPERR 0x0082
ian@0 38 #define MCHK_K_HERR 0x0084
ian@0 39 #define MCHK_K_ECC_C 0x0086
ian@0 40 #define MCHK_K_ECC_NC 0x0088
ian@0 41 #define MCHK_K_UNKNOWN 0x008A
ian@0 42 #define MCHK_K_CACKSOFT 0x008C
ian@0 43 #define MCHK_K_BUGCHECK 0x008E
ian@0 44 #define MCHK_K_OS_BUGCHECK 0x0090
ian@0 45 #define MCHK_K_DCPERR 0x0092
ian@0 46 #define MCHK_K_ICPERR 0x0094
ian@0 47
ian@0 48
ian@0 49 /*
ian@0 50 * Platform-specific machine-check reasons:
ian@0 51 */
ian@0 52 #define MCHK_K_SIO_SERR 0x204 /* all platforms so far */
ian@0 53 #define MCHK_K_SIO_IOCHK 0x206 /* all platforms so far */
ian@0 54 #define MCHK_K_DCSR 0x208 /* all but Noname */
ian@0 55
ian@0 56
ian@0 57 /*
ian@0 58 * Given a bus, device, and function number, compute resulting
ian@0 59 * configuration space address and setup the LCA_IOC_CONF register
ian@0 60 * accordingly. It is therefore not safe to have concurrent
ian@0 61 * invocations to configuration space access routines, but there
ian@0 62 * really shouldn't be any need for this.
ian@0 63 *
ian@0 64 * Type 0:
ian@0 65 *
ian@0 66 * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1
ian@0 67 * 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0
ian@0 68 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
ian@0 69 * | | | | | | | | | | | | | | | | | | | | | | | |F|F|F|R|R|R|R|R|R|0|0|
ian@0 70 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
ian@0 71 *
ian@0 72 * 31:11 Device select bit.
ian@0 73 * 10:8 Function number
ian@0 74 * 7:2 Register number
ian@0 75 *
ian@0 76 * Type 1:
ian@0 77 *
ian@0 78 * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1
ian@0 79 * 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0
ian@0 80 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
ian@0 81 * | | | | | | | | | | |B|B|B|B|B|B|B|B|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|1|
ian@0 82 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
ian@0 83 *
ian@0 84 * 31:24 reserved
ian@0 85 * 23:16 bus number (8 bits = 128 possible buses)
ian@0 86 * 15:11 Device number (5 bits)
ian@0 87 * 10:8 function number
ian@0 88 * 7:2 register number
ian@0 89 *
ian@0 90 * Notes:
ian@0 91 * The function number selects which function of a multi-function device
ian@0 92 * (e.g., SCSI and Ethernet).
ian@0 93 *
ian@0 94 * The register selects a DWORD (32 bit) register offset. Hence it
ian@0 95 * doesn't get shifted by 2 bits as we want to "drop" the bottom two
ian@0 96 * bits.
ian@0 97 */
ian@0 98
ian@0 99 static int
ian@0 100 mk_conf_addr(struct pci_bus *pbus, unsigned int device_fn, int where,
ian@0 101 unsigned long *pci_addr)
ian@0 102 {
ian@0 103 unsigned long addr;
ian@0 104 u8 bus = pbus->number;
ian@0 105
ian@0 106 if (bus == 0) {
ian@0 107 int device = device_fn >> 3;
ian@0 108 int func = device_fn & 0x7;
ian@0 109
ian@0 110 /* Type 0 configuration cycle. */
ian@0 111
ian@0 112 if (device > 12) {
ian@0 113 return -1;
ian@0 114 }
ian@0 115
ian@0 116 *(vulp)LCA_IOC_CONF = 0;
ian@0 117 addr = (1 << (11 + device)) | (func << 8) | where;
ian@0 118 } else {
ian@0 119 /* Type 1 configuration cycle. */
ian@0 120 *(vulp)LCA_IOC_CONF = 1;
ian@0 121 addr = (bus << 16) | (device_fn << 8) | where;
ian@0 122 }
ian@0 123 *pci_addr = addr;
ian@0 124 return 0;
ian@0 125 }
ian@0 126
ian@0 127 static unsigned int
ian@0 128 conf_read(unsigned long addr)
ian@0 129 {
ian@0 130 unsigned long flags, code, stat0;
ian@0 131 unsigned int value;
ian@0 132
ian@0 133 local_irq_save(flags);
ian@0 134
ian@0 135 /* Reset status register to avoid loosing errors. */
ian@0 136 stat0 = *(vulp)LCA_IOC_STAT0;
ian@0 137 *(vulp)LCA_IOC_STAT0 = stat0;
ian@0 138 mb();
ian@0 139
ian@0 140 /* Access configuration space. */
ian@0 141 value = *(vuip)addr;
ian@0 142 draina();
ian@0 143
ian@0 144 stat0 = *(vulp)LCA_IOC_STAT0;
ian@0 145 if (stat0 & LCA_IOC_STAT0_ERR) {
ian@0 146 code = ((stat0 >> LCA_IOC_STAT0_CODE_SHIFT)
ian@0 147 & LCA_IOC_STAT0_CODE_MASK);
ian@0 148 if (code != 1) {
ian@0 149 printk("lca.c:conf_read: got stat0=%lx\n", stat0);
ian@0 150 }
ian@0 151
ian@0 152 /* Reset error status. */
ian@0 153 *(vulp)LCA_IOC_STAT0 = stat0;
ian@0 154 mb();
ian@0 155
ian@0 156 /* Reset machine check. */
ian@0 157 wrmces(0x7);
ian@0 158
ian@0 159 value = 0xffffffff;
ian@0 160 }
ian@0 161 local_irq_restore(flags);
ian@0 162 return value;
ian@0 163 }
ian@0 164
ian@0 165 static void
ian@0 166 conf_write(unsigned long addr, unsigned int value)
ian@0 167 {
ian@0 168 unsigned long flags, code, stat0;
ian@0 169
ian@0 170 local_irq_save(flags); /* avoid getting hit by machine check */
ian@0 171
ian@0 172 /* Reset status register to avoid loosing errors. */
ian@0 173 stat0 = *(vulp)LCA_IOC_STAT0;
ian@0 174 *(vulp)LCA_IOC_STAT0 = stat0;
ian@0 175 mb();
ian@0 176
ian@0 177 /* Access configuration space. */
ian@0 178 *(vuip)addr = value;
ian@0 179 draina();
ian@0 180
ian@0 181 stat0 = *(vulp)LCA_IOC_STAT0;
ian@0 182 if (stat0 & LCA_IOC_STAT0_ERR) {
ian@0 183 code = ((stat0 >> LCA_IOC_STAT0_CODE_SHIFT)
ian@0 184 & LCA_IOC_STAT0_CODE_MASK);
ian@0 185 if (code != 1) {
ian@0 186 printk("lca.c:conf_write: got stat0=%lx\n", stat0);
ian@0 187 }
ian@0 188
ian@0 189 /* Reset error status. */
ian@0 190 *(vulp)LCA_IOC_STAT0 = stat0;
ian@0 191 mb();
ian@0 192
ian@0 193 /* Reset machine check. */
ian@0 194 wrmces(0x7);
ian@0 195 }
ian@0 196 local_irq_restore(flags);
ian@0 197 }
ian@0 198
ian@0 199 static int
ian@0 200 lca_read_config(struct pci_bus *bus, unsigned int devfn, int where,
ian@0 201 int size, u32 *value)
ian@0 202 {
ian@0 203 unsigned long addr, pci_addr;
ian@0 204 long mask;
ian@0 205 int shift;
ian@0 206
ian@0 207 if (mk_conf_addr(bus, devfn, where, &pci_addr))
ian@0 208 return PCIBIOS_DEVICE_NOT_FOUND;
ian@0 209
ian@0 210 shift = (where & 3) * 8;
ian@0 211 mask = (size - 1) * 8;
ian@0 212 addr = (pci_addr << 5) + mask + LCA_CONF;
ian@0 213 *value = conf_read(addr) >> (shift);
ian@0 214 return PCIBIOS_SUCCESSFUL;
ian@0 215 }
ian@0 216
ian@0 217 static int
ian@0 218 lca_write_config(struct pci_bus *bus, unsigned int devfn, int where, int size,
ian@0 219 u32 value)
ian@0 220 {
ian@0 221 unsigned long addr, pci_addr;
ian@0 222 long mask;
ian@0 223
ian@0 224 if (mk_conf_addr(bus, devfn, where, &pci_addr))
ian@0 225 return PCIBIOS_DEVICE_NOT_FOUND;
ian@0 226
ian@0 227 mask = (size - 1) * 8;
ian@0 228 addr = (pci_addr << 5) + mask + LCA_CONF;
ian@0 229 conf_write(addr, value << ((where & 3) * 8));
ian@0 230 return PCIBIOS_SUCCESSFUL;
ian@0 231 }
ian@0 232
ian@0 233 struct pci_ops lca_pci_ops =
ian@0 234 {
ian@0 235 .read = lca_read_config,
ian@0 236 .write = lca_write_config,
ian@0 237 };
ian@0 238
ian@0 239 void
ian@0 240 lca_pci_tbi(struct pci_controller *hose, dma_addr_t start, dma_addr_t end)
ian@0 241 {
ian@0 242 wmb();
ian@0 243 *(vulp)LCA_IOC_TBIA = 0;
ian@0 244 mb();
ian@0 245 }
ian@0 246
ian@0 247 void __init
ian@0 248 lca_init_arch(void)
ian@0 249 {
ian@0 250 struct pci_controller *hose;
ian@0 251
ian@0 252 /*
ian@0 253 * Create our single hose.
ian@0 254 */
ian@0 255
ian@0 256 pci_isa_hose = hose = alloc_pci_controller();
ian@0 257 hose->io_space = &ioport_resource;
ian@0 258 hose->mem_space = &iomem_resource;
ian@0 259 hose->index = 0;
ian@0 260
ian@0 261 hose->sparse_mem_base = LCA_SPARSE_MEM - IDENT_ADDR;
ian@0 262 hose->dense_mem_base = LCA_DENSE_MEM - IDENT_ADDR;
ian@0 263 hose->sparse_io_base = LCA_IO - IDENT_ADDR;
ian@0 264 hose->dense_io_base = 0;
ian@0 265
ian@0 266 /*
ian@0 267 * Set up the PCI to main memory translation windows.
ian@0 268 *
ian@0 269 * Mimic the SRM settings for the direct-map window.
ian@0 270 * Window 0 is scatter-gather 8MB at 8MB (for isa).
ian@0 271 * Window 1 is direct access 1GB at 1GB.
ian@0 272 *
ian@0 273 * Note that we do not try to save any of the DMA window CSRs
ian@0 274 * before setting them, since we cannot read those CSRs on LCA.
ian@0 275 */
ian@0 276 hose->sg_isa = iommu_arena_new(hose, 0x00800000, 0x00800000, 0);
ian@0 277 hose->sg_pci = NULL;
ian@0 278 __direct_map_base = 0x40000000;
ian@0 279 __direct_map_size = 0x40000000;
ian@0 280
ian@0 281 *(vulp)LCA_IOC_W_BASE0 = hose->sg_isa->dma_base | (3UL << 32);
ian@0 282 *(vulp)LCA_IOC_W_MASK0 = (hose->sg_isa->size - 1) & 0xfff00000;
ian@0 283 *(vulp)LCA_IOC_T_BASE0 = virt_to_phys(hose->sg_isa->ptes);
ian@0 284
ian@0 285 *(vulp)LCA_IOC_W_BASE1 = __direct_map_base | (2UL << 32);
ian@0 286 *(vulp)LCA_IOC_W_MASK1 = (__direct_map_size - 1) & 0xfff00000;
ian@0 287 *(vulp)LCA_IOC_T_BASE1 = 0;
ian@0 288
ian@0 289 *(vulp)LCA_IOC_TB_ENA = 0x80;
ian@0 290
ian@0 291 lca_pci_tbi(hose, 0, -1);
ian@0 292
ian@0 293 /*
ian@0 294 * Disable PCI parity for now. The NCR53c810 chip has
ian@0 295 * troubles meeting the PCI spec which results in
ian@0 296 * data parity errors.
ian@0 297 */
ian@0 298 *(vulp)LCA_IOC_PAR_DIS = 1UL<<5;
ian@0 299
ian@0 300 /*
ian@0 301 * Finally, set up for restoring the correct HAE if using SRM.
ian@0 302 * Again, since we cannot read many of the CSRs on the LCA,
ian@0 303 * one of which happens to be the HAE, we save the value that
ian@0 304 * the SRM will expect...
ian@0 305 */
ian@0 306 if (alpha_using_srm)
ian@0 307 srm_hae = 0x80000000UL;
ian@0 308 }
ian@0 309
ian@0 310 /*
ian@0 311 * Constants used during machine-check handling. I suppose these
ian@0 312 * could be moved into lca.h but I don't see much reason why anybody
ian@0 313 * else would want to use them.
ian@0 314 */
ian@0 315
ian@0 316 #define ESR_EAV (1UL<< 0) /* error address valid */
ian@0 317 #define ESR_CEE (1UL<< 1) /* correctable error */
ian@0 318 #define ESR_UEE (1UL<< 2) /* uncorrectable error */
ian@0 319 #define ESR_WRE (1UL<< 3) /* write-error */
ian@0 320 #define ESR_SOR (1UL<< 4) /* error source */
ian@0 321 #define ESR_CTE (1UL<< 7) /* cache-tag error */
ian@0 322 #define ESR_MSE (1UL<< 9) /* multiple soft errors */
ian@0 323 #define ESR_MHE (1UL<<10) /* multiple hard errors */
ian@0 324 #define ESR_NXM (1UL<<12) /* non-existent memory */
ian@0 325
ian@0 326 #define IOC_ERR ( 1<<4) /* ioc logs an error */
ian@0 327 #define IOC_CMD_SHIFT 0
ian@0 328 #define IOC_CMD (0xf<<IOC_CMD_SHIFT)
ian@0 329 #define IOC_CODE_SHIFT 8
ian@0 330 #define IOC_CODE (0xf<<IOC_CODE_SHIFT)
ian@0 331 #define IOC_LOST ( 1<<5)
ian@0 332 #define IOC_P_NBR ((__u32) ~((1<<13) - 1))
ian@0 333
ian@0 334 static void
ian@0 335 mem_error(unsigned long esr, unsigned long ear)
ian@0 336 {
ian@0 337 printk(" %s %s error to %s occurred at address %x\n",
ian@0 338 ((esr & ESR_CEE) ? "Correctable" :
ian@0 339 (esr & ESR_UEE) ? "Uncorrectable" : "A"),
ian@0 340 (esr & ESR_WRE) ? "write" : "read",
ian@0 341 (esr & ESR_SOR) ? "memory" : "b-cache",
ian@0 342 (unsigned) (ear & 0x1ffffff8));
ian@0 343 if (esr & ESR_CTE) {
ian@0 344 printk(" A b-cache tag parity error was detected.\n");
ian@0 345 }
ian@0 346 if (esr & ESR_MSE) {
ian@0 347 printk(" Several other correctable errors occurred.\n");
ian@0 348 }
ian@0 349 if (esr & ESR_MHE) {
ian@0 350 printk(" Several other uncorrectable errors occurred.\n");
ian@0 351 }
ian@0 352 if (esr & ESR_NXM) {
ian@0 353 printk(" Attempted to access non-existent memory.\n");
ian@0 354 }
ian@0 355 }
ian@0 356
ian@0 357 static void
ian@0 358 ioc_error(__u32 stat0, __u32 stat1)
ian@0 359 {
ian@0 360 static const char * const pci_cmd[] = {
ian@0 361 "Interrupt Acknowledge", "Special", "I/O Read", "I/O Write",
ian@0 362 "Rsvd 1", "Rsvd 2", "Memory Read", "Memory Write", "Rsvd3",
ian@0 363 "Rsvd4", "Configuration Read", "Configuration Write",
ian@0 364 "Memory Read Multiple", "Dual Address", "Memory Read Line",
ian@0 365 "Memory Write and Invalidate"
ian@0 366 };
ian@0 367 static const char * const err_name[] = {
ian@0 368 "exceeded retry limit", "no device", "bad data parity",
ian@0 369 "target abort", "bad address parity", "page table read error",
ian@0 370 "invalid page", "data error"
ian@0 371 };
ian@0 372 unsigned code = (stat0 & IOC_CODE) >> IOC_CODE_SHIFT;
ian@0 373 unsigned cmd = (stat0 & IOC_CMD) >> IOC_CMD_SHIFT;
ian@0 374
ian@0 375 printk(" %s initiated PCI %s cycle to address %x"
ian@0 376 " failed due to %s.\n",
ian@0 377 code > 3 ? "PCI" : "CPU", pci_cmd[cmd], stat1, err_name[code]);
ian@0 378
ian@0 379 if (code == 5 || code == 6) {
ian@0 380 printk(" (Error occurred at PCI memory address %x.)\n",
ian@0 381 (stat0 & ~IOC_P_NBR));
ian@0 382 }
ian@0 383 if (stat0 & IOC_LOST) {
ian@0 384 printk(" Other PCI errors occurred simultaneously.\n");
ian@0 385 }
ian@0 386 }
ian@0 387
ian@0 388 void
ian@0 389 lca_machine_check(unsigned long vector, unsigned long la_ptr,
ian@0 390 struct pt_regs *regs)
ian@0 391 {
ian@0 392 const char * reason;
ian@0 393 union el_lca el;
ian@0 394
ian@0 395 el.c = (struct el_common *) la_ptr;
ian@0 396
ian@0 397 wrmces(rdmces()); /* reset machine check pending flag */
ian@0 398
ian@0 399 printk(KERN_CRIT "LCA machine check: vector=%#lx pc=%#lx code=%#x\n",
ian@0 400 vector, regs->pc, (unsigned int) el.c->code);
ian@0 401
ian@0 402 /*
ian@0 403 * The first quadword after the common header always seems to
ian@0 404 * be the machine check reason---don't know why this isn't
ian@0 405 * part of the common header instead. In the case of a long
ian@0 406 * logout frame, the upper 32 bits is the machine check
ian@0 407 * revision level, which we ignore for now.
ian@0 408 */
ian@0 409 switch ((unsigned int) el.c->code) {
ian@0 410 case MCHK_K_TPERR: reason = "tag parity error"; break;
ian@0 411 case MCHK_K_TCPERR: reason = "tag control parity error"; break;
ian@0 412 case MCHK_K_HERR: reason = "access to non-existent memory"; break;
ian@0 413 case MCHK_K_ECC_C: reason = "correctable ECC error"; break;
ian@0 414 case MCHK_K_ECC_NC: reason = "non-correctable ECC error"; break;
ian@0 415 case MCHK_K_CACKSOFT: reason = "MCHK_K_CACKSOFT"; break;
ian@0 416 case MCHK_K_BUGCHECK: reason = "illegal exception in PAL mode"; break;
ian@0 417 case MCHK_K_OS_BUGCHECK: reason = "callsys in kernel mode"; break;
ian@0 418 case MCHK_K_DCPERR: reason = "d-cache parity error"; break;
ian@0 419 case MCHK_K_ICPERR: reason = "i-cache parity error"; break;
ian@0 420 case MCHK_K_SIO_SERR: reason = "SIO SERR occurred on PCI bus"; break;
ian@0 421 case MCHK_K_SIO_IOCHK: reason = "SIO IOCHK occurred on ISA bus"; break;
ian@0 422 case MCHK_K_DCSR: reason = "MCHK_K_DCSR"; break;
ian@0 423 case MCHK_K_UNKNOWN:
ian@0 424 default: reason = "unknown"; break;
ian@0 425 }
ian@0 426
ian@0 427 switch (el.c->size) {
ian@0 428 case sizeof(struct el_lca_mcheck_short):
ian@0 429 printk(KERN_CRIT
ian@0 430 " Reason: %s (short frame%s, dc_stat=%#lx):\n",
ian@0 431 reason, el.c->retry ? ", retryable" : "",
ian@0 432 el.s->dc_stat);
ian@0 433 if (el.s->esr & ESR_EAV) {
ian@0 434 mem_error(el.s->esr, el.s->ear);
ian@0 435 }
ian@0 436 if (el.s->ioc_stat0 & IOC_ERR) {
ian@0 437 ioc_error(el.s->ioc_stat0, el.s->ioc_stat1);
ian@0 438 }
ian@0 439 break;
ian@0 440
ian@0 441 case sizeof(struct el_lca_mcheck_long):
ian@0 442 printk(KERN_CRIT " Reason: %s (long frame%s):\n",
ian@0 443 reason, el.c->retry ? ", retryable" : "");
ian@0 444 printk(KERN_CRIT
ian@0 445 " reason: %#lx exc_addr: %#lx dc_stat: %#lx\n",
ian@0 446 el.l->pt[0], el.l->exc_addr, el.l->dc_stat);
ian@0 447 printk(KERN_CRIT " car: %#lx\n", el.l->car);
ian@0 448 if (el.l->esr & ESR_EAV) {
ian@0 449 mem_error(el.l->esr, el.l->ear);
ian@0 450 }
ian@0 451 if (el.l->ioc_stat0 & IOC_ERR) {
ian@0 452 ioc_error(el.l->ioc_stat0, el.l->ioc_stat1);
ian@0 453 }
ian@0 454 break;
ian@0 455
ian@0 456 default:
ian@0 457 printk(KERN_CRIT " Unknown errorlog size %d\n", el.c->size);
ian@0 458 }
ian@0 459
ian@0 460 /* Dump the logout area to give all info. */
ian@0 461 #ifdef CONFIG_VERBOSE_MCHECK
ian@0 462 if (alpha_verbose_mcheck > 1) {
ian@0 463 unsigned long * ptr = (unsigned long *) la_ptr;
ian@0 464 long i;
ian@0 465 for (i = 0; i < el.c->size / sizeof(long); i += 2) {
ian@0 466 printk(KERN_CRIT " +%8lx %016lx %016lx\n",
ian@0 467 i*sizeof(long), ptr[i], ptr[i+1]);
ian@0 468 }
ian@0 469 }
ian@0 470 #endif /* CONFIG_VERBOSE_MCHECK */
ian@0 471 }
ian@0 472
ian@0 473 /*
ian@0 474 * The following routines are needed to support the SPEED changing
ian@0 475 * necessary to successfully manage the thermal problem on the AlphaBook1.
ian@0 476 */
ian@0 477
ian@0 478 void
ian@0 479 lca_clock_print(void)
ian@0 480 {
ian@0 481 long pmr_reg;
ian@0 482
ian@0 483 pmr_reg = LCA_READ_PMR;
ian@0 484
ian@0 485 printk("Status of clock control:\n");
ian@0 486 printk("\tPrimary clock divisor\t0x%lx\n", LCA_GET_PRIMARY(pmr_reg));
ian@0 487 printk("\tOverride clock divisor\t0x%lx\n", LCA_GET_OVERRIDE(pmr_reg));
ian@0 488 printk("\tInterrupt override is %s\n",
ian@0 489 (pmr_reg & LCA_PMR_INTO) ? "on" : "off");
ian@0 490 printk("\tDMA override is %s\n",
ian@0 491 (pmr_reg & LCA_PMR_DMAO) ? "on" : "off");
ian@0 492
ian@0 493 }
ian@0 494
ian@0 495 int
ian@0 496 lca_get_clock(void)
ian@0 497 {
ian@0 498 long pmr_reg;
ian@0 499
ian@0 500 pmr_reg = LCA_READ_PMR;
ian@0 501 return(LCA_GET_PRIMARY(pmr_reg));
ian@0 502
ian@0 503 }
ian@0 504
ian@0 505 void
ian@0 506 lca_clock_fiddle(int divisor)
ian@0 507 {
ian@0 508 long pmr_reg;
ian@0 509
ian@0 510 pmr_reg = LCA_READ_PMR;
ian@0 511 LCA_SET_PRIMARY_CLOCK(pmr_reg, divisor);
ian@0 512 /* lca_norm_clock = divisor; */
ian@0 513 LCA_WRITE_PMR(pmr_reg);
ian@0 514 mb();
ian@0 515 }