vserver 1.9.3
[linux-2.6.git] / arch / x86_64 / kernel / i8259.c
index c52b859..f5d084a 100644 (file)
@@ -329,7 +329,7 @@ spurious_8259A_irq:
                 * lets ACK and report it. [once per IRQ]
                 */
                if (!(spurious_irq_mask & irqmask)) {
-                       printk("spurious 8259A interrupt: IRQ%d.\n", irq);
+                       printk(KERN_DEBUG "spurious 8259A interrupt: IRQ%d.\n", irq);
                        spurious_irq_mask |= irqmask;
                }
                atomic_inc(&irq_err_count);
@@ -342,7 +342,7 @@ spurious_8259A_irq:
        }
 }
 
-void __init init_8259A(int auto_eoi)
+void init_8259A(int auto_eoi)
 {
        unsigned long flags;
 
@@ -385,6 +385,57 @@ void __init init_8259A(int auto_eoi)
        spin_unlock_irqrestore(&i8259A_lock, flags);
 }
 
+static char irq_trigger[2];
+/**
+ * ELCR registers (0x4d0, 0x4d1) control edge/level of IRQ
+ */
+static void restore_ELCR(char *trigger)
+{
+       outb(trigger[0], 0x4d0);
+       outb(trigger[1], 0x4d1);
+}
+
+static void save_ELCR(char *trigger)
+{
+       /* IRQ 0,1,2,8,13 are marked as reserved */
+       trigger[0] = inb(0x4d0) & 0xF8;
+       trigger[1] = inb(0x4d1) & 0xDE;
+}
+
+static int i8259A_resume(struct sys_device *dev)
+{
+       init_8259A(0);
+       restore_ELCR(irq_trigger);
+       return 0;
+}
+
+static int i8259A_suspend(struct sys_device *dev, u32 state)
+{
+       save_ELCR(irq_trigger);
+       return 0;
+}
+
+static struct sysdev_class i8259_sysdev_class = {
+       set_kset_name("i8259"),
+       .suspend = i8259A_suspend,
+       .resume = i8259A_resume,
+};
+
+static struct sys_device device_i8259A = {
+       .id     = 0,
+       .cls    = &i8259_sysdev_class,
+};
+
+static int __init i8259A_init_sysfs(void)
+{
+       int error = sysdev_class_register(&i8259_sysdev_class);
+       if (!error)
+               error = sysdev_register(&device_i8259A);
+       return error;
+}
+
+device_initcall(i8259A_init_sysfs);
+
 /*
  * IRQ2 is cascade interrupt to second interrupt controller
  */