ia64/linux-2.6.18-xen.hg

annotate arch/alpha/kernel/sys_sable.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/sys_sable.c
ian@0 3 *
ian@0 4 * Copyright (C) 1995 David A Rusling
ian@0 5 * Copyright (C) 1996 Jay A Estabrook
ian@0 6 * Copyright (C) 1998, 1999 Richard Henderson
ian@0 7 *
ian@0 8 * Code supporting the Sable, Sable-Gamma, and Lynx systems.
ian@0 9 */
ian@0 10
ian@0 11 #include <linux/kernel.h>
ian@0 12 #include <linux/types.h>
ian@0 13 #include <linux/mm.h>
ian@0 14 #include <linux/sched.h>
ian@0 15 #include <linux/pci.h>
ian@0 16 #include <linux/init.h>
ian@0 17
ian@0 18 #include <asm/ptrace.h>
ian@0 19 #include <asm/system.h>
ian@0 20 #include <asm/dma.h>
ian@0 21 #include <asm/irq.h>
ian@0 22 #include <asm/mmu_context.h>
ian@0 23 #include <asm/io.h>
ian@0 24 #include <asm/pgtable.h>
ian@0 25 #include <asm/core_t2.h>
ian@0 26 #include <asm/tlbflush.h>
ian@0 27
ian@0 28 #include "proto.h"
ian@0 29 #include "irq_impl.h"
ian@0 30 #include "pci_impl.h"
ian@0 31 #include "machvec_impl.h"
ian@0 32
ian@0 33 DEFINE_SPINLOCK(sable_lynx_irq_lock);
ian@0 34
ian@0 35 typedef struct irq_swizzle_struct
ian@0 36 {
ian@0 37 char irq_to_mask[64];
ian@0 38 char mask_to_irq[64];
ian@0 39
ian@0 40 /* Note mask bit is true for DISABLED irqs. */
ian@0 41 unsigned long shadow_mask;
ian@0 42
ian@0 43 void (*update_irq_hw)(unsigned long bit, unsigned long mask);
ian@0 44 void (*ack_irq_hw)(unsigned long bit);
ian@0 45
ian@0 46 } irq_swizzle_t;
ian@0 47
ian@0 48 static irq_swizzle_t *sable_lynx_irq_swizzle;
ian@0 49
ian@0 50 static void sable_lynx_init_irq(int nr_irqs);
ian@0 51
ian@0 52 #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SABLE)
ian@0 53
ian@0 54 /***********************************************************************/
ian@0 55 /*
ian@0 56 * For SABLE, which is really baroque, we manage 40 IRQ's, but the
ian@0 57 * hardware really only supports 24, not via normal ISA PIC,
ian@0 58 * but cascaded custom 8259's, etc.
ian@0 59 * 0-7 (char at 536)
ian@0 60 * 8-15 (char at 53a)
ian@0 61 * 16-23 (char at 53c)
ian@0 62 *
ian@0 63 * Summary Registers (536/53a/53c):
ian@0 64 *
ian@0 65 * Bit Meaning Kernel IRQ
ian@0 66 *------------------------------------------
ian@0 67 * 0 PCI slot 0 34
ian@0 68 * 1 NCR810 (builtin) 33
ian@0 69 * 2 TULIP (builtin) 32
ian@0 70 * 3 mouse 12
ian@0 71 * 4 PCI slot 1 35
ian@0 72 * 5 PCI slot 2 36
ian@0 73 * 6 keyboard 1
ian@0 74 * 7 floppy 6
ian@0 75 * 8 COM2 3
ian@0 76 * 9 parallel port 7
ian@0 77 *10 EISA irq 3 -
ian@0 78 *11 EISA irq 4 -
ian@0 79 *12 EISA irq 5 5
ian@0 80 *13 EISA irq 6 -
ian@0 81 *14 EISA irq 7 -
ian@0 82 *15 COM1 4
ian@0 83 *16 EISA irq 9 9
ian@0 84 *17 EISA irq 10 10
ian@0 85 *18 EISA irq 11 11
ian@0 86 *19 EISA irq 12 -
ian@0 87 *20 EISA irq 13 -
ian@0 88 *21 EISA irq 14 14
ian@0 89 *22 NC 15
ian@0 90 *23 IIC -
ian@0 91 */
ian@0 92
ian@0 93 static void
ian@0 94 sable_update_irq_hw(unsigned long bit, unsigned long mask)
ian@0 95 {
ian@0 96 int port = 0x537;
ian@0 97
ian@0 98 if (bit >= 16) {
ian@0 99 port = 0x53d;
ian@0 100 mask >>= 16;
ian@0 101 } else if (bit >= 8) {
ian@0 102 port = 0x53b;
ian@0 103 mask >>= 8;
ian@0 104 }
ian@0 105
ian@0 106 outb(mask, port);
ian@0 107 }
ian@0 108
ian@0 109 static void
ian@0 110 sable_ack_irq_hw(unsigned long bit)
ian@0 111 {
ian@0 112 int port, val1, val2;
ian@0 113
ian@0 114 if (bit >= 16) {
ian@0 115 port = 0x53c;
ian@0 116 val1 = 0xE0 | (bit - 16);
ian@0 117 val2 = 0xE0 | 4;
ian@0 118 } else if (bit >= 8) {
ian@0 119 port = 0x53a;
ian@0 120 val1 = 0xE0 | (bit - 8);
ian@0 121 val2 = 0xE0 | 3;
ian@0 122 } else {
ian@0 123 port = 0x536;
ian@0 124 val1 = 0xE0 | (bit - 0);
ian@0 125 val2 = 0xE0 | 1;
ian@0 126 }
ian@0 127
ian@0 128 outb(val1, port); /* ack the slave */
ian@0 129 outb(val2, 0x534); /* ack the master */
ian@0 130 }
ian@0 131
ian@0 132 static irq_swizzle_t sable_irq_swizzle = {
ian@0 133 {
ian@0 134 -1, 6, -1, 8, 15, 12, 7, 9, /* pseudo PIC 0-7 */
ian@0 135 -1, 16, 17, 18, 3, -1, 21, 22, /* pseudo PIC 8-15 */
ian@0 136 -1, -1, -1, -1, -1, -1, -1, -1, /* pseudo EISA 0-7 */
ian@0 137 -1, -1, -1, -1, -1, -1, -1, -1, /* pseudo EISA 8-15 */
ian@0 138 2, 1, 0, 4, 5, -1, -1, -1, /* pseudo PCI */
ian@0 139 -1, -1, -1, -1, -1, -1, -1, -1, /* */
ian@0 140 -1, -1, -1, -1, -1, -1, -1, -1, /* */
ian@0 141 -1, -1, -1, -1, -1, -1, -1, -1 /* */
ian@0 142 },
ian@0 143 {
ian@0 144 34, 33, 32, 12, 35, 36, 1, 6, /* mask 0-7 */
ian@0 145 3, 7, -1, -1, 5, -1, -1, 4, /* mask 8-15 */
ian@0 146 9, 10, 11, -1, -1, 14, 15, -1, /* mask 16-23 */
ian@0 147 -1, -1, -1, -1, -1, -1, -1, -1, /* */
ian@0 148 -1, -1, -1, -1, -1, -1, -1, -1, /* */
ian@0 149 -1, -1, -1, -1, -1, -1, -1, -1, /* */
ian@0 150 -1, -1, -1, -1, -1, -1, -1, -1, /* */
ian@0 151 -1, -1, -1, -1, -1, -1, -1, -1 /* */
ian@0 152 },
ian@0 153 -1,
ian@0 154 sable_update_irq_hw,
ian@0 155 sable_ack_irq_hw
ian@0 156 };
ian@0 157
ian@0 158 static void __init
ian@0 159 sable_init_irq(void)
ian@0 160 {
ian@0 161 outb(-1, 0x537); /* slave 0 */
ian@0 162 outb(-1, 0x53b); /* slave 1 */
ian@0 163 outb(-1, 0x53d); /* slave 2 */
ian@0 164 outb(0x44, 0x535); /* enable cascades in master */
ian@0 165
ian@0 166 sable_lynx_irq_swizzle = &sable_irq_swizzle;
ian@0 167 sable_lynx_init_irq(40);
ian@0 168 }
ian@0 169
ian@0 170 /*
ian@0 171 * PCI Fixup configuration for ALPHA SABLE (2100).
ian@0 172 *
ian@0 173 * The device to slot mapping looks like:
ian@0 174 *
ian@0 175 * Slot Device
ian@0 176 * 0 TULIP
ian@0 177 * 1 SCSI
ian@0 178 * 2 PCI-EISA bridge
ian@0 179 * 3 none
ian@0 180 * 4 none
ian@0 181 * 5 none
ian@0 182 * 6 PCI on board slot 0
ian@0 183 * 7 PCI on board slot 1
ian@0 184 * 8 PCI on board slot 2
ian@0 185 *
ian@0 186 *
ian@0 187 * This two layered interrupt approach means that we allocate IRQ 16 and
ian@0 188 * above for PCI interrupts. The IRQ relates to which bit the interrupt
ian@0 189 * comes in on. This makes interrupt processing much easier.
ian@0 190 */
ian@0 191 /*
ian@0 192 * NOTE: the IRQ assignments below are arbitrary, but need to be consistent
ian@0 193 * with the values in the irq swizzling tables above.
ian@0 194 */
ian@0 195
ian@0 196 static int __init
ian@0 197 sable_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
ian@0 198 {
ian@0 199 static char irq_tab[9][5] __initdata = {
ian@0 200 /*INT INTA INTB INTC INTD */
ian@0 201 { 32+0, 32+0, 32+0, 32+0, 32+0}, /* IdSel 0, TULIP */
ian@0 202 { 32+1, 32+1, 32+1, 32+1, 32+1}, /* IdSel 1, SCSI */
ian@0 203 { -1, -1, -1, -1, -1}, /* IdSel 2, SIO */
ian@0 204 { -1, -1, -1, -1, -1}, /* IdSel 3, none */
ian@0 205 { -1, -1, -1, -1, -1}, /* IdSel 4, none */
ian@0 206 { -1, -1, -1, -1, -1}, /* IdSel 5, none */
ian@0 207 { 32+2, 32+2, 32+2, 32+2, 32+2}, /* IdSel 6, slot 0 */
ian@0 208 { 32+3, 32+3, 32+3, 32+3, 32+3}, /* IdSel 7, slot 1 */
ian@0 209 { 32+4, 32+4, 32+4, 32+4, 32+4} /* IdSel 8, slot 2 */
ian@0 210 };
ian@0 211 long min_idsel = 0, max_idsel = 8, irqs_per_slot = 5;
ian@0 212 return COMMON_TABLE_LOOKUP;
ian@0 213 }
ian@0 214 #endif /* defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SABLE) */
ian@0 215
ian@0 216 #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_LYNX)
ian@0 217
ian@0 218 /***********************************************************************/
ian@0 219 /* LYNX hardware specifics
ian@0 220 */
ian@0 221 /*
ian@0 222 * For LYNX, which is also baroque, we manage 64 IRQs, via a custom IC.
ian@0 223 *
ian@0 224 * Bit Meaning Kernel IRQ
ian@0 225 *------------------------------------------
ian@0 226 * 0
ian@0 227 * 1
ian@0 228 * 2
ian@0 229 * 3 mouse 12
ian@0 230 * 4
ian@0 231 * 5
ian@0 232 * 6 keyboard 1
ian@0 233 * 7 floppy 6
ian@0 234 * 8 COM2 3
ian@0 235 * 9 parallel port 7
ian@0 236 *10 EISA irq 3 -
ian@0 237 *11 EISA irq 4 -
ian@0 238 *12 EISA irq 5 5
ian@0 239 *13 EISA irq 6 -
ian@0 240 *14 EISA irq 7 -
ian@0 241 *15 COM1 4
ian@0 242 *16 EISA irq 9 9
ian@0 243 *17 EISA irq 10 10
ian@0 244 *18 EISA irq 11 11
ian@0 245 *19 EISA irq 12 -
ian@0 246 *20
ian@0 247 *21 EISA irq 14 14
ian@0 248 *22 EISA irq 15 15
ian@0 249 *23 IIC -
ian@0 250 *24 VGA (builtin) -
ian@0 251 *25
ian@0 252 *26
ian@0 253 *27
ian@0 254 *28 NCR810 (builtin) 28
ian@0 255 *29
ian@0 256 *30
ian@0 257 *31
ian@0 258 *32 PCI 0 slot 4 A primary bus 32
ian@0 259 *33 PCI 0 slot 4 B primary bus 33
ian@0 260 *34 PCI 0 slot 4 C primary bus 34
ian@0 261 *35 PCI 0 slot 4 D primary bus
ian@0 262 *36 PCI 0 slot 5 A primary bus
ian@0 263 *37 PCI 0 slot 5 B primary bus
ian@0 264 *38 PCI 0 slot 5 C primary bus
ian@0 265 *39 PCI 0 slot 5 D primary bus
ian@0 266 *40 PCI 0 slot 6 A primary bus
ian@0 267 *41 PCI 0 slot 6 B primary bus
ian@0 268 *42 PCI 0 slot 6 C primary bus
ian@0 269 *43 PCI 0 slot 6 D primary bus
ian@0 270 *44 PCI 0 slot 7 A primary bus
ian@0 271 *45 PCI 0 slot 7 B primary bus
ian@0 272 *46 PCI 0 slot 7 C primary bus
ian@0 273 *47 PCI 0 slot 7 D primary bus
ian@0 274 *48 PCI 0 slot 0 A secondary bus
ian@0 275 *49 PCI 0 slot 0 B secondary bus
ian@0 276 *50 PCI 0 slot 0 C secondary bus
ian@0 277 *51 PCI 0 slot 0 D secondary bus
ian@0 278 *52 PCI 0 slot 1 A secondary bus
ian@0 279 *53 PCI 0 slot 1 B secondary bus
ian@0 280 *54 PCI 0 slot 1 C secondary bus
ian@0 281 *55 PCI 0 slot 1 D secondary bus
ian@0 282 *56 PCI 0 slot 2 A secondary bus
ian@0 283 *57 PCI 0 slot 2 B secondary bus
ian@0 284 *58 PCI 0 slot 2 C secondary bus
ian@0 285 *59 PCI 0 slot 2 D secondary bus
ian@0 286 *60 PCI 0 slot 3 A secondary bus
ian@0 287 *61 PCI 0 slot 3 B secondary bus
ian@0 288 *62 PCI 0 slot 3 C secondary bus
ian@0 289 *63 PCI 0 slot 3 D secondary bus
ian@0 290 */
ian@0 291
ian@0 292 static void
ian@0 293 lynx_update_irq_hw(unsigned long bit, unsigned long mask)
ian@0 294 {
ian@0 295 /*
ian@0 296 * Write the AIR register on the T3/T4 with the
ian@0 297 * address of the IC mask register (offset 0x40)
ian@0 298 */
ian@0 299 *(vulp)T2_AIR = 0x40;
ian@0 300 mb();
ian@0 301 *(vulp)T2_AIR; /* re-read to force write */
ian@0 302 mb();
ian@0 303 *(vulp)T2_DIR = mask;
ian@0 304 mb();
ian@0 305 mb();
ian@0 306 }
ian@0 307
ian@0 308 static void
ian@0 309 lynx_ack_irq_hw(unsigned long bit)
ian@0 310 {
ian@0 311 *(vulp)T2_VAR = (u_long) bit;
ian@0 312 mb();
ian@0 313 mb();
ian@0 314 }
ian@0 315
ian@0 316 static irq_swizzle_t lynx_irq_swizzle = {
ian@0 317 { /* irq_to_mask */
ian@0 318 -1, 6, -1, 8, 15, 12, 7, 9, /* pseudo PIC 0-7 */
ian@0 319 -1, 16, 17, 18, 3, -1, 21, 22, /* pseudo PIC 8-15 */
ian@0 320 -1, -1, -1, -1, -1, -1, -1, -1, /* pseudo */
ian@0 321 -1, -1, -1, -1, 28, -1, -1, -1, /* pseudo */
ian@0 322 32, 33, 34, 35, 36, 37, 38, 39, /* mask 32-39 */
ian@0 323 40, 41, 42, 43, 44, 45, 46, 47, /* mask 40-47 */
ian@0 324 48, 49, 50, 51, 52, 53, 54, 55, /* mask 48-55 */
ian@0 325 56, 57, 58, 59, 60, 61, 62, 63 /* mask 56-63 */
ian@0 326 },
ian@0 327 { /* mask_to_irq */
ian@0 328 -1, -1, -1, 12, -1, -1, 1, 6, /* mask 0-7 */
ian@0 329 3, 7, -1, -1, 5, -1, -1, 4, /* mask 8-15 */
ian@0 330 9, 10, 11, -1, -1, 14, 15, -1, /* mask 16-23 */
ian@0 331 -1, -1, -1, -1, 28, -1, -1, -1, /* mask 24-31 */
ian@0 332 32, 33, 34, 35, 36, 37, 38, 39, /* mask 32-39 */
ian@0 333 40, 41, 42, 43, 44, 45, 46, 47, /* mask 40-47 */
ian@0 334 48, 49, 50, 51, 52, 53, 54, 55, /* mask 48-55 */
ian@0 335 56, 57, 58, 59, 60, 61, 62, 63 /* mask 56-63 */
ian@0 336 },
ian@0 337 -1,
ian@0 338 lynx_update_irq_hw,
ian@0 339 lynx_ack_irq_hw
ian@0 340 };
ian@0 341
ian@0 342 static void __init
ian@0 343 lynx_init_irq(void)
ian@0 344 {
ian@0 345 sable_lynx_irq_swizzle = &lynx_irq_swizzle;
ian@0 346 sable_lynx_init_irq(64);
ian@0 347 }
ian@0 348
ian@0 349 /*
ian@0 350 * PCI Fixup configuration for ALPHA LYNX (2100A)
ian@0 351 *
ian@0 352 * The device to slot mapping looks like:
ian@0 353 *
ian@0 354 * Slot Device
ian@0 355 * 0 none
ian@0 356 * 1 none
ian@0 357 * 2 PCI-EISA bridge
ian@0 358 * 3 PCI-PCI bridge
ian@0 359 * 4 NCR 810 (Demi-Lynx only)
ian@0 360 * 5 none
ian@0 361 * 6 PCI on board slot 4
ian@0 362 * 7 PCI on board slot 5
ian@0 363 * 8 PCI on board slot 6
ian@0 364 * 9 PCI on board slot 7
ian@0 365 *
ian@0 366 * And behind the PPB we have:
ian@0 367 *
ian@0 368 * 11 PCI on board slot 0
ian@0 369 * 12 PCI on board slot 1
ian@0 370 * 13 PCI on board slot 2
ian@0 371 * 14 PCI on board slot 3
ian@0 372 */
ian@0 373 /*
ian@0 374 * NOTE: the IRQ assignments below are arbitrary, but need to be consistent
ian@0 375 * with the values in the irq swizzling tables above.
ian@0 376 */
ian@0 377
ian@0 378 static int __init
ian@0 379 lynx_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
ian@0 380 {
ian@0 381 static char irq_tab[19][5] __initdata = {
ian@0 382 /*INT INTA INTB INTC INTD */
ian@0 383 { -1, -1, -1, -1, -1}, /* IdSel 13, PCEB */
ian@0 384 { -1, -1, -1, -1, -1}, /* IdSel 14, PPB */
ian@0 385 { 28, 28, 28, 28, 28}, /* IdSel 15, NCR demi */
ian@0 386 { -1, -1, -1, -1, -1}, /* IdSel 16, none */
ian@0 387 { 32, 32, 33, 34, 35}, /* IdSel 17, slot 4 */
ian@0 388 { 36, 36, 37, 38, 39}, /* IdSel 18, slot 5 */
ian@0 389 { 40, 40, 41, 42, 43}, /* IdSel 19, slot 6 */
ian@0 390 { 44, 44, 45, 46, 47}, /* IdSel 20, slot 7 */
ian@0 391 { -1, -1, -1, -1, -1}, /* IdSel 22, none */
ian@0 392 /* The following are actually behind the PPB. */
ian@0 393 { -1, -1, -1, -1, -1}, /* IdSel 16 none */
ian@0 394 { 28, 28, 28, 28, 28}, /* IdSel 17 NCR lynx */
ian@0 395 { -1, -1, -1, -1, -1}, /* IdSel 18 none */
ian@0 396 { -1, -1, -1, -1, -1}, /* IdSel 19 none */
ian@0 397 { -1, -1, -1, -1, -1}, /* IdSel 20 none */
ian@0 398 { -1, -1, -1, -1, -1}, /* IdSel 21 none */
ian@0 399 { 48, 48, 49, 50, 51}, /* IdSel 22 slot 0 */
ian@0 400 { 52, 52, 53, 54, 55}, /* IdSel 23 slot 1 */
ian@0 401 { 56, 56, 57, 58, 59}, /* IdSel 24 slot 2 */
ian@0 402 { 60, 60, 61, 62, 63} /* IdSel 25 slot 3 */
ian@0 403 };
ian@0 404 const long min_idsel = 2, max_idsel = 20, irqs_per_slot = 5;
ian@0 405 return COMMON_TABLE_LOOKUP;
ian@0 406 }
ian@0 407
ian@0 408 static u8 __init
ian@0 409 lynx_swizzle(struct pci_dev *dev, u8 *pinp)
ian@0 410 {
ian@0 411 int slot, pin = *pinp;
ian@0 412
ian@0 413 if (dev->bus->number == 0) {
ian@0 414 slot = PCI_SLOT(dev->devfn);
ian@0 415 }
ian@0 416 /* Check for the built-in bridge */
ian@0 417 else if (PCI_SLOT(dev->bus->self->devfn) == 3) {
ian@0 418 slot = PCI_SLOT(dev->devfn) + 11;
ian@0 419 }
ian@0 420 else
ian@0 421 {
ian@0 422 /* Must be a card-based bridge. */
ian@0 423 do {
ian@0 424 if (PCI_SLOT(dev->bus->self->devfn) == 3) {
ian@0 425 slot = PCI_SLOT(dev->devfn) + 11;
ian@0 426 break;
ian@0 427 }
ian@0 428 pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn)) ;
ian@0 429
ian@0 430 /* Move up the chain of bridges. */
ian@0 431 dev = dev->bus->self;
ian@0 432 /* Slot of the next bridge. */
ian@0 433 slot = PCI_SLOT(dev->devfn);
ian@0 434 } while (dev->bus->self);
ian@0 435 }
ian@0 436 *pinp = pin;
ian@0 437 return slot;
ian@0 438 }
ian@0 439
ian@0 440 #endif /* defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_LYNX) */
ian@0 441
ian@0 442 /***********************************************************************/
ian@0 443 /* GENERIC irq routines */
ian@0 444
ian@0 445 static inline void
ian@0 446 sable_lynx_enable_irq(unsigned int irq)
ian@0 447 {
ian@0 448 unsigned long bit, mask;
ian@0 449
ian@0 450 bit = sable_lynx_irq_swizzle->irq_to_mask[irq];
ian@0 451 spin_lock(&sable_lynx_irq_lock);
ian@0 452 mask = sable_lynx_irq_swizzle->shadow_mask &= ~(1UL << bit);
ian@0 453 sable_lynx_irq_swizzle->update_irq_hw(bit, mask);
ian@0 454 spin_unlock(&sable_lynx_irq_lock);
ian@0 455 #if 0
ian@0 456 printk("%s: mask 0x%lx bit 0x%x irq 0x%x\n",
ian@0 457 __FUNCTION__, mask, bit, irq);
ian@0 458 #endif
ian@0 459 }
ian@0 460
ian@0 461 static void
ian@0 462 sable_lynx_disable_irq(unsigned int irq)
ian@0 463 {
ian@0 464 unsigned long bit, mask;
ian@0 465
ian@0 466 bit = sable_lynx_irq_swizzle->irq_to_mask[irq];
ian@0 467 spin_lock(&sable_lynx_irq_lock);
ian@0 468 mask = sable_lynx_irq_swizzle->shadow_mask |= 1UL << bit;
ian@0 469 sable_lynx_irq_swizzle->update_irq_hw(bit, mask);
ian@0 470 spin_unlock(&sable_lynx_irq_lock);
ian@0 471 #if 0
ian@0 472 printk("%s: mask 0x%lx bit 0x%x irq 0x%x\n",
ian@0 473 __FUNCTION__, mask, bit, irq);
ian@0 474 #endif
ian@0 475 }
ian@0 476
ian@0 477 static unsigned int
ian@0 478 sable_lynx_startup_irq(unsigned int irq)
ian@0 479 {
ian@0 480 sable_lynx_enable_irq(irq);
ian@0 481 return 0;
ian@0 482 }
ian@0 483
ian@0 484 static void
ian@0 485 sable_lynx_end_irq(unsigned int irq)
ian@0 486 {
ian@0 487 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
ian@0 488 sable_lynx_enable_irq(irq);
ian@0 489 }
ian@0 490
ian@0 491 static void
ian@0 492 sable_lynx_mask_and_ack_irq(unsigned int irq)
ian@0 493 {
ian@0 494 unsigned long bit, mask;
ian@0 495
ian@0 496 bit = sable_lynx_irq_swizzle->irq_to_mask[irq];
ian@0 497 spin_lock(&sable_lynx_irq_lock);
ian@0 498 mask = sable_lynx_irq_swizzle->shadow_mask |= 1UL << bit;
ian@0 499 sable_lynx_irq_swizzle->update_irq_hw(bit, mask);
ian@0 500 sable_lynx_irq_swizzle->ack_irq_hw(bit);
ian@0 501 spin_unlock(&sable_lynx_irq_lock);
ian@0 502 }
ian@0 503
ian@0 504 static struct hw_interrupt_type sable_lynx_irq_type = {
ian@0 505 .typename = "SABLE/LYNX",
ian@0 506 .startup = sable_lynx_startup_irq,
ian@0 507 .shutdown = sable_lynx_disable_irq,
ian@0 508 .enable = sable_lynx_enable_irq,
ian@0 509 .disable = sable_lynx_disable_irq,
ian@0 510 .ack = sable_lynx_mask_and_ack_irq,
ian@0 511 .end = sable_lynx_end_irq,
ian@0 512 };
ian@0 513
ian@0 514 static void
ian@0 515 sable_lynx_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
ian@0 516 {
ian@0 517 /* Note that the vector reported by the SRM PALcode corresponds
ian@0 518 to the interrupt mask bits, but we have to manage via the
ian@0 519 so-called legacy IRQs for many common devices. */
ian@0 520
ian@0 521 int bit, irq;
ian@0 522
ian@0 523 bit = (vector - 0x800) >> 4;
ian@0 524 irq = sable_lynx_irq_swizzle->mask_to_irq[bit];
ian@0 525 #if 0
ian@0 526 printk("%s: vector 0x%lx bit 0x%x irq 0x%x\n",
ian@0 527 __FUNCTION__, vector, bit, irq);
ian@0 528 #endif
ian@0 529 handle_irq(irq, regs);
ian@0 530 }
ian@0 531
ian@0 532 static void __init
ian@0 533 sable_lynx_init_irq(int nr_irqs)
ian@0 534 {
ian@0 535 long i;
ian@0 536
ian@0 537 for (i = 0; i < nr_irqs; ++i) {
ian@0 538 irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
ian@0 539 irq_desc[i].chip = &sable_lynx_irq_type;
ian@0 540 }
ian@0 541
ian@0 542 common_init_isa_dma();
ian@0 543 }
ian@0 544
ian@0 545 static void __init
ian@0 546 sable_lynx_init_pci(void)
ian@0 547 {
ian@0 548 common_init_pci();
ian@0 549 }
ian@0 550
ian@0 551 /*****************************************************************/
ian@0 552 /*
ian@0 553 * The System Vectors
ian@0 554 *
ian@0 555 * In order that T2_HAE_ADDRESS should be a constant, we play
ian@0 556 * these games with GAMMA_BIAS.
ian@0 557 */
ian@0 558
ian@0 559 #if defined(CONFIG_ALPHA_GENERIC) || \
ian@0 560 (defined(CONFIG_ALPHA_SABLE) && !defined(CONFIG_ALPHA_GAMMA))
ian@0 561 #undef GAMMA_BIAS
ian@0 562 #define GAMMA_BIAS 0
ian@0 563 struct alpha_machine_vector sable_mv __initmv = {
ian@0 564 .vector_name = "Sable",
ian@0 565 DO_EV4_MMU,
ian@0 566 DO_DEFAULT_RTC,
ian@0 567 DO_T2_IO,
ian@0 568 .machine_check = t2_machine_check,
ian@0 569 .max_isa_dma_address = ALPHA_SABLE_MAX_ISA_DMA_ADDRESS,
ian@0 570 .min_io_address = EISA_DEFAULT_IO_BASE,
ian@0 571 .min_mem_address = T2_DEFAULT_MEM_BASE,
ian@0 572
ian@0 573 .nr_irqs = 40,
ian@0 574 .device_interrupt = sable_lynx_srm_device_interrupt,
ian@0 575
ian@0 576 .init_arch = t2_init_arch,
ian@0 577 .init_irq = sable_init_irq,
ian@0 578 .init_rtc = common_init_rtc,
ian@0 579 .init_pci = sable_lynx_init_pci,
ian@0 580 .kill_arch = t2_kill_arch,
ian@0 581 .pci_map_irq = sable_map_irq,
ian@0 582 .pci_swizzle = common_swizzle,
ian@0 583
ian@0 584 .sys = { .t2 = {
ian@0 585 .gamma_bias = 0
ian@0 586 } }
ian@0 587 };
ian@0 588 ALIAS_MV(sable)
ian@0 589 #endif /* GENERIC || (SABLE && !GAMMA) */
ian@0 590
ian@0 591 #if defined(CONFIG_ALPHA_GENERIC) || \
ian@0 592 (defined(CONFIG_ALPHA_SABLE) && defined(CONFIG_ALPHA_GAMMA))
ian@0 593 #undef GAMMA_BIAS
ian@0 594 #define GAMMA_BIAS _GAMMA_BIAS
ian@0 595 struct alpha_machine_vector sable_gamma_mv __initmv = {
ian@0 596 .vector_name = "Sable-Gamma",
ian@0 597 DO_EV5_MMU,
ian@0 598 DO_DEFAULT_RTC,
ian@0 599 DO_T2_IO,
ian@0 600 .machine_check = t2_machine_check,
ian@0 601 .max_isa_dma_address = ALPHA_SABLE_MAX_ISA_DMA_ADDRESS,
ian@0 602 .min_io_address = EISA_DEFAULT_IO_BASE,
ian@0 603 .min_mem_address = T2_DEFAULT_MEM_BASE,
ian@0 604
ian@0 605 .nr_irqs = 40,
ian@0 606 .device_interrupt = sable_lynx_srm_device_interrupt,
ian@0 607
ian@0 608 .init_arch = t2_init_arch,
ian@0 609 .init_irq = sable_init_irq,
ian@0 610 .init_rtc = common_init_rtc,
ian@0 611 .init_pci = sable_lynx_init_pci,
ian@0 612 .kill_arch = t2_kill_arch,
ian@0 613 .pci_map_irq = sable_map_irq,
ian@0 614 .pci_swizzle = common_swizzle,
ian@0 615
ian@0 616 .sys = { .t2 = {
ian@0 617 .gamma_bias = _GAMMA_BIAS
ian@0 618 } }
ian@0 619 };
ian@0 620 ALIAS_MV(sable_gamma)
ian@0 621 #endif /* GENERIC || (SABLE && GAMMA) */
ian@0 622
ian@0 623 #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_LYNX)
ian@0 624 #undef GAMMA_BIAS
ian@0 625 #define GAMMA_BIAS _GAMMA_BIAS
ian@0 626 struct alpha_machine_vector lynx_mv __initmv = {
ian@0 627 .vector_name = "Lynx",
ian@0 628 DO_EV4_MMU,
ian@0 629 DO_DEFAULT_RTC,
ian@0 630 DO_T2_IO,
ian@0 631 .machine_check = t2_machine_check,
ian@0 632 .max_isa_dma_address = ALPHA_SABLE_MAX_ISA_DMA_ADDRESS,
ian@0 633 .min_io_address = EISA_DEFAULT_IO_BASE,
ian@0 634 .min_mem_address = T2_DEFAULT_MEM_BASE,
ian@0 635
ian@0 636 .nr_irqs = 64,
ian@0 637 .device_interrupt = sable_lynx_srm_device_interrupt,
ian@0 638
ian@0 639 .init_arch = t2_init_arch,
ian@0 640 .init_irq = lynx_init_irq,
ian@0 641 .init_rtc = common_init_rtc,
ian@0 642 .init_pci = sable_lynx_init_pci,
ian@0 643 .kill_arch = t2_kill_arch,
ian@0 644 .pci_map_irq = lynx_map_irq,
ian@0 645 .pci_swizzle = lynx_swizzle,
ian@0 646
ian@0 647 .sys = { .t2 = {
ian@0 648 .gamma_bias = _GAMMA_BIAS
ian@0 649 } }
ian@0 650 };
ian@0 651 ALIAS_MV(lynx)
ian@0 652 #endif /* GENERIC || LYNX */