Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph...
[pandora-kernel.git] / arch / x86 / kernel / apic / io_apic.c
index 180ca24..45fd33d 100644 (file)
@@ -30,7 +30,7 @@
 #include <linux/compiler.h>
 #include <linux/acpi.h>
 #include <linux/module.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
 #include <linux/msi.h>
 #include <linux/htirq.h>
 #include <linux/freezer.h>
@@ -128,8 +128,8 @@ static int __init parse_noapic(char *str)
 }
 early_param("noapic", parse_noapic);
 
-static int io_apic_setup_irq_pin_once(unsigned int irq, int node,
-                                     struct io_apic_irq_attr *attr);
+static int io_apic_setup_irq_pin(unsigned int irq, int node,
+                                struct io_apic_irq_attr *attr);
 
 /* Will be called in mpparse/acpi/sfi codes for saving IRQ info */
 void mp_save_irq(struct mpc_intsrc *m)
@@ -2918,89 +2918,84 @@ static int __init io_apic_bug_finalize(void)
 
 late_initcall(io_apic_bug_finalize);
 
-struct sysfs_ioapic_data {
-       struct sys_device dev;
-       struct IO_APIC_route_entry entry[0];
-};
-static struct sysfs_ioapic_data * mp_ioapic_data[MAX_IO_APICS];
+static struct IO_APIC_route_entry *ioapic_saved_data[MAX_IO_APICS];
 
-static int ioapic_suspend(struct sys_device *dev, pm_message_t state)
+static void suspend_ioapic(int ioapic_id)
 {
-       struct IO_APIC_route_entry *entry;
-       struct sysfs_ioapic_data *data;
+       struct IO_APIC_route_entry *saved_data = ioapic_saved_data[ioapic_id];
        int i;
 
-       data = container_of(dev, struct sysfs_ioapic_data, dev);
-       entry = data->entry;
-       for (i = 0; i < nr_ioapic_registers[dev->id]; i ++, entry ++ )
-               *entry = ioapic_read_entry(dev->id, i);
+       if (!saved_data)
+               return;
+
+       for (i = 0; i < nr_ioapic_registers[ioapic_id]; i++)
+               saved_data[i] = ioapic_read_entry(ioapic_id, i);
+}
+
+static int ioapic_suspend(void)
+{
+       int ioapic_id;
+
+       for (ioapic_id = 0; ioapic_id < nr_ioapics; ioapic_id++)
+               suspend_ioapic(ioapic_id);
 
        return 0;
 }
 
-static int ioapic_resume(struct sys_device *dev)
+static void resume_ioapic(int ioapic_id)
 {
-       struct IO_APIC_route_entry *entry;
-       struct sysfs_ioapic_data *data;
+       struct IO_APIC_route_entry *saved_data = ioapic_saved_data[ioapic_id];
        unsigned long flags;
        union IO_APIC_reg_00 reg_00;
        int i;
 
-       data = container_of(dev, struct sysfs_ioapic_data, dev);
-       entry = data->entry;
+       if (!saved_data)
+               return;
 
        raw_spin_lock_irqsave(&ioapic_lock, flags);
-       reg_00.raw = io_apic_read(dev->id, 0);
-       if (reg_00.bits.ID != mp_ioapics[dev->id].apicid) {
-               reg_00.bits.ID = mp_ioapics[dev->id].apicid;
-               io_apic_write(dev->id, 0, reg_00.raw);
+       reg_00.raw = io_apic_read(ioapic_id, 0);
+       if (reg_00.bits.ID != mp_ioapics[ioapic_id].apicid) {
+               reg_00.bits.ID = mp_ioapics[ioapic_id].apicid;
+               io_apic_write(ioapic_id, 0, reg_00.raw);
        }
        raw_spin_unlock_irqrestore(&ioapic_lock, flags);
-       for (i = 0; i < nr_ioapic_registers[dev->id]; i++)
-               ioapic_write_entry(dev->id, i, entry[i]);
+       for (i = 0; i < nr_ioapic_registers[ioapic_id]; i++)
+               ioapic_write_entry(ioapic_id, i, saved_data[i]);
+}
 
-       return 0;
+static void ioapic_resume(void)
+{
+       int ioapic_id;
+
+       for (ioapic_id = nr_ioapics - 1; ioapic_id >= 0; ioapic_id--)
+               resume_ioapic(ioapic_id);
 }
 
-static struct sysdev_class ioapic_sysdev_class = {
-       .name = "ioapic",
+static struct syscore_ops ioapic_syscore_ops = {
        .suspend = ioapic_suspend,
        .resume = ioapic_resume,
 };
 
-static int __init ioapic_init_sysfs(void)
+static int __init ioapic_init_ops(void)
 {
-       struct sys_device * dev;
-       int i, size, error;
+       int i;
 
-       error = sysdev_class_register(&ioapic_sysdev_class);
-       if (error)
-               return error;
+       for (i = 0; i < nr_ioapics; i++) {
+               unsigned int size;
 
-       for (i = 0; i < nr_ioapics; i++ ) {
-               size = sizeof(struct sys_device) + nr_ioapic_registers[i]
+               size = nr_ioapic_registers[i]
                        * sizeof(struct IO_APIC_route_entry);
-               mp_ioapic_data[i] = kzalloc(size, GFP_KERNEL);
-               if (!mp_ioapic_data[i]) {
-                       printk(KERN_ERR "Can't suspend/resume IOAPIC %d\n", i);
-                       continue;
-               }
-               dev = &mp_ioapic_data[i]->dev;
-               dev->id = i;
-               dev->cls = &ioapic_sysdev_class;
-               error = sysdev_register(dev);
-               if (error) {
-                       kfree(mp_ioapic_data[i]);
-                       mp_ioapic_data[i] = NULL;
-                       printk(KERN_ERR "Can't suspend/resume IOAPIC %d\n", i);
-                       continue;
-               }
+               ioapic_saved_data[i] = kzalloc(size, GFP_KERNEL);
+               if (!ioapic_saved_data[i])
+                       pr_err("IOAPIC %d: suspend/resume impossible!\n", i);
        }
 
+       register_syscore_ops(&ioapic_syscore_ops);
+
        return 0;
 }
 
-device_initcall(ioapic_init_sysfs);
+device_initcall(ioapic_init_ops);
 
 /*
  * Dynamic irq allocate and deallocation
@@ -3575,7 +3570,7 @@ int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
 }
 #endif /* CONFIG_HT_IRQ */
 
-int
+static int
 io_apic_setup_irq_pin(unsigned int irq, int node, struct io_apic_irq_attr *attr)
 {
        struct irq_cfg *cfg = alloc_irq_and_cfg_at(irq, node);
@@ -3590,8 +3585,8 @@ io_apic_setup_irq_pin(unsigned int irq, int node, struct io_apic_irq_attr *attr)
        return ret;
 }
 
-static int io_apic_setup_irq_pin_once(unsigned int irq, int node,
-                                     struct io_apic_irq_attr *attr)
+int io_apic_setup_irq_pin_once(unsigned int irq, int node,
+                              struct io_apic_irq_attr *attr)
 {
        unsigned int id = attr->ioapic, pin = attr->ioapic_pin;
        int ret;