Merge trivial low-risk suspend hotkey bugzilla-5918 into release
Len Brown [Mon, 21 Aug 2006 01:49:29 +0000 (21:49 -0400)]
16 files changed:
MAINTAINERS
arch/i386/kernel/acpi/boot.c
arch/i386/kernel/acpi/wakeup.S
arch/ia64/kernel/acpi.c
drivers/acpi/ac.c
drivers/acpi/acpi_memhotplug.c
drivers/acpi/battery.c
drivers/acpi/bus.c
drivers/acpi/hotkey.c
drivers/acpi/i2c_ec.c
drivers/acpi/osl.c
drivers/acpi/sbs.c
drivers/acpi/scan.c
drivers/acpi/utils.c
drivers/pci/hotplug/Kconfig
drivers/pci/quirks.c

index 21116cc..3bab239 100644 (file)
@@ -889,6 +889,12 @@ M: rdunlap@xenotime.net
 T:     git http://tali.admingilde.org/git/linux-docbook.git
 S:     Maintained
 
+DOCKING STATION DRIVER
+P:     Kristen Carlson Accardi
+M:     kristen.c.accardi@intel.com
+L:     linux-acpi@vger.kernel.org
+S:     Maintained
+
 DOUBLETALK DRIVER
 P:     James R. Van Zandt
 M:     jrv@vanzandt.mv.com
index 0db6387..ee003bc 100644 (file)
@@ -59,7 +59,7 @@ static inline int gsi_irq_sharing(int gsi) { return gsi; }
 
 #define BAD_MADT_ENTRY(entry, end) (                                       \
                (!entry) || (unsigned long)entry + sizeof(*entry) > end ||  \
-               ((acpi_table_entry_header *)entry)->length != sizeof(*entry))
+               ((acpi_table_entry_header *)entry)->length < sizeof(*entry))
 
 #define PREFIX                 "ACPI: "
 
index 9f408ee..b781b38 100644 (file)
@@ -292,7 +292,10 @@ ENTRY(do_suspend_lowlevel)
        pushl   $3
        call    acpi_enter_sleep_state
        addl    $4, %esp
-       ret
+
+#      In case of S3 failure, we'll emerge here.  Jump
+#      to ret_point to recover
+       jmp     ret_point
        .p2align 4,,7
 ret_point:
        call    restore_registers
index 99761b8..0176556 100644 (file)
@@ -55,7 +55,7 @@
 
 #define BAD_MADT_ENTRY(entry, end) (                                        \
                (!entry) || (unsigned long)entry + sizeof(*entry) > end ||  \
-               ((acpi_table_entry_header *)entry)->length != sizeof(*entry))
+               ((acpi_table_entry_header *)entry)->length < sizeof(*entry))
 
 #define PREFIX                 "ACPI: "
 
index 96309b9..11abc7b 100644 (file)
@@ -285,6 +285,8 @@ static int __init acpi_ac_init(void)
 {
        int result;
 
+       if (acpi_disabled)
+               return -ENODEV;
 
        acpi_ac_dir = acpi_lock_ac_dir();
        if (!acpi_ac_dir)
index b0d4b14..1dda370 100644 (file)
@@ -484,10 +484,8 @@ acpi_memory_register_notify_handler(acpi_handle handle,
 
 
        status = is_memory_device(handle);
-       if (ACPI_FAILURE(status)){
-               ACPI_EXCEPTION((AE_INFO, status, "handle is no memory device"));
+       if (ACPI_FAILURE(status))
                return AE_OK;   /* continue */
-       }
 
        status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
                                             acpi_memory_device_notify, NULL);
@@ -503,10 +501,8 @@ acpi_memory_deregister_notify_handler(acpi_handle handle,
 
 
        status = is_memory_device(handle);
-       if (ACPI_FAILURE(status)){
-               ACPI_EXCEPTION((AE_INFO, status, "handle is no memory device"));
+       if (ACPI_FAILURE(status))
                return AE_OK;   /* continue */
-       }
 
        status = acpi_remove_notify_handler(handle,
                                            ACPI_SYSTEM_NOTIFY,
index 6e52217..9810e2a 100644 (file)
@@ -757,6 +757,9 @@ static int __init acpi_battery_init(void)
 {
        int result;
 
+       if (acpi_disabled)
+               return -ENODEV;
+
        acpi_battery_dir = acpi_lock_battery_dir();
        if (!acpi_battery_dir)
                return -ENODEV;
index b297769..279c4ba 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/ioport.h>
+#include <linux/kernel.h>
 #include <linux/list.h>
 #include <linux/sched.h>
 #include <linux/pm.h>
@@ -68,7 +69,8 @@ int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device)
 
        status = acpi_get_data(handle, acpi_bus_data_handler, (void **)device);
        if (ACPI_FAILURE(status) || !*device) {
-               ACPI_EXCEPTION((AE_INFO, status, "No context for object [%p]", handle));
+               ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No context for object [%p]\n",
+                                 handle));
                return -ENODEV;
        }
 
@@ -192,7 +194,7 @@ int acpi_bus_set_power(acpi_handle handle, int state)
        /* Make sure this is a valid target state */
 
        if (!device->flags.power_manageable) {
-               ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device `[%s]' is not power manageable",
+               ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device `[%s]' is not power manageable\n",
                                device->kobj.name));
                return -ENODEV;
        }
@@ -738,7 +740,10 @@ static int __init acpi_init(void)
                return -ENODEV;
        }
 
-       firmware_register(&acpi_subsys);
+       result = firmware_register(&acpi_subsys);
+       if (result < 0)
+               printk(KERN_WARNING "%s: firmware_register error: %d\n",
+                       __FUNCTION__, result);
 
        result = acpi_bus_init();
 
index 32c9d88..1ba2db6 100644 (file)
@@ -91,6 +91,14 @@ enum {
        HK_EVENT_ENTERRING_S5,
 };
 
+enum conf_entry_enum {
+       bus_handle = 0,
+       bus_method = 1,
+       action_handle = 2,
+       method = 3,
+       LAST_CONF_ENTRY
+};
+
 /*  procdir we use */
 static struct proc_dir_entry *hotkey_proc_dir;
 static struct proc_dir_entry *hotkey_config;
@@ -244,19 +252,15 @@ static int hotkey_info_open_fs(struct inode *inode, struct file *file)
 
 static char *format_result(union acpi_object *object)
 {
-       char *buf = NULL;
-
-       buf = (char *)kmalloc(RESULT_STR_LEN, GFP_KERNEL);
-       if (buf)
-               memset(buf, 0, RESULT_STR_LEN);
-       else
-               goto do_fail;
+       char *buf;
 
+       buf = kzalloc(RESULT_STR_LEN, GFP_KERNEL);
+       if (!buf)
+               return NULL;
        /* Now, just support integer type */
        if (object->type == ACPI_TYPE_INTEGER)
                sprintf(buf, "%d\n", (u32) object->integer.value);
-      do_fail:
-       return (buf);
+       return buf;
 }
 
 static int hotkey_polling_seq_show(struct seq_file *seq, void *offset)
@@ -486,98 +490,102 @@ static void free_hotkey_device(union acpi_hotkey *key)
 
 static void free_hotkey_buffer(union acpi_hotkey *key)
 {
+       /* key would never be null, action method could be */
        kfree(key->event_hotkey.action_method);
 }
 
 static void free_poll_hotkey_buffer(union acpi_hotkey *key)
 {
+       /* key would never be null, others could be*/
        kfree(key->poll_hotkey.action_method);
        kfree(key->poll_hotkey.poll_method);
        kfree(key->poll_hotkey.poll_result);
 }
 static int
-init_hotkey_device(union acpi_hotkey *key, char *bus_str, char *action_str,
-                  char *method, int std_num, int external_num)
+init_hotkey_device(union acpi_hotkey *key, char **config_entry,
+                  int std_num, int external_num)
 {
        acpi_handle tmp_handle;
        acpi_status status = AE_OK;
 
-
        if (std_num < 0 || IS_POLL(std_num) || !key)
                goto do_fail;
 
-       if (!bus_str || !action_str || !method)
+       if (!config_entry[bus_handle] || !config_entry[action_handle]
+                       || !config_entry[method])
                goto do_fail;
 
        key->link.hotkey_type = ACPI_HOTKEY_EVENT;
        key->link.hotkey_standard_num = std_num;
        key->event_hotkey.flag = 0;
-       key->event_hotkey.action_method = method;
+       key->event_hotkey.action_method = config_entry[method];
 
-       status =
-           acpi_get_handle(NULL, bus_str, &(key->event_hotkey.bus_handle));
+       status = acpi_get_handle(NULL, config_entry[bus_handle],
+                          &(key->event_hotkey.bus_handle));
        if (ACPI_FAILURE(status))
-               goto do_fail;
+               goto do_fail_zero;
        key->event_hotkey.external_hotkey_num = external_num;
-       status =
-           acpi_get_handle(NULL, action_str,
+       status = acpi_get_handle(NULL, config_entry[action_handle],
                            &(key->event_hotkey.action_handle));
        if (ACPI_FAILURE(status))
-               goto do_fail;
+               goto do_fail_zero;
        status = acpi_get_handle(key->event_hotkey.action_handle,
-                                method, &tmp_handle);
+                                config_entry[method], &tmp_handle);
        if (ACPI_FAILURE(status))
-               goto do_fail;
+               goto do_fail_zero;
        return AE_OK;
-      do_fail:
+do_fail_zero:
+       key->event_hotkey.action_method = NULL;
+do_fail:
        return -ENODEV;
 }
 
 static int
-init_poll_hotkey_device(union acpi_hotkey *key,
-                       char *poll_str,
-                       char *poll_method,
-                       char *action_str, char *action_method, int std_num)
+init_poll_hotkey_device(union acpi_hotkey *key, char **config_entry,
+                       int std_num)
 {
        acpi_status status = AE_OK;
        acpi_handle tmp_handle;
 
-
        if (std_num < 0 || IS_EVENT(std_num) || !key)
                goto do_fail;
-
-       if (!poll_str || !poll_method || !action_str || !action_method)
+       if (!config_entry[bus_handle] ||!config_entry[bus_method] ||
+               !config_entry[action_handle] || !config_entry[method])
                goto do_fail;
 
        key->link.hotkey_type = ACPI_HOTKEY_POLLING;
        key->link.hotkey_standard_num = std_num;
        key->poll_hotkey.flag = 0;
-       key->poll_hotkey.poll_method = poll_method;
-       key->poll_hotkey.action_method = action_method;
+       key->poll_hotkey.poll_method = config_entry[bus_method];
+       key->poll_hotkey.action_method = config_entry[method];
 
-       status =
-           acpi_get_handle(NULL, poll_str, &(key->poll_hotkey.poll_handle));
+       status = acpi_get_handle(NULL, config_entry[bus_handle],
+                     &(key->poll_hotkey.poll_handle));
        if (ACPI_FAILURE(status))
-               goto do_fail;
+               goto do_fail_zero;
        status = acpi_get_handle(key->poll_hotkey.poll_handle,
-                                poll_method, &tmp_handle);
+                                config_entry[bus_method], &tmp_handle);
        if (ACPI_FAILURE(status))
-               goto do_fail;
+               goto do_fail_zero;
        status =
-           acpi_get_handle(NULL, action_str,
+           acpi_get_handle(NULL, config_entry[action_handle],
                            &(key->poll_hotkey.action_handle));
        if (ACPI_FAILURE(status))
-               goto do_fail;
+               goto do_fail_zero;
        status = acpi_get_handle(key->poll_hotkey.action_handle,
-                                action_method, &tmp_handle);
+                                config_entry[method], &tmp_handle);
        if (ACPI_FAILURE(status))
-               goto do_fail;
+               goto do_fail_zero;
        key->poll_hotkey.poll_result =
            (union acpi_object *)kmalloc(sizeof(union acpi_object), GFP_KERNEL);
        if (!key->poll_hotkey.poll_result)
-               goto do_fail;
+               goto do_fail_zero;
        return AE_OK;
-      do_fail:
+
+do_fail_zero:
+       key->poll_hotkey.poll_method = NULL;
+       key->poll_hotkey.action_method = NULL;
+do_fail:
        return -ENODEV;
 }
 
@@ -652,17 +660,18 @@ static int hotkey_poll_config_seq_show(struct seq_file *seq, void *offset)
 }
 
 static int
-get_parms(char *config_record,
-         int *cmd,
-         char **bus_handle,
-         char **bus_method,
-         char **action_handle,
-         char **method, int *internal_event_num, int *external_event_num)
+get_parms(char *config_record, int *cmd, char **config_entry,
+              int *internal_event_num, int *external_event_num)
 {
+/* the format of *config_record =
+ * "1:\d+:*" : "cmd:internal_event_num"
+ * "\d+:\w+:\w+:\w+:\w+:\d+:\d+" :
+ * "cmd:bus_handle:bus_method:action_handle:method:internal_event_num:external_event_num"
+ */
        char *tmp, *tmp1, count;
+       int i;
 
        sscanf(config_record, "%d", cmd);
-
        if (*cmd == 1) {
                if (sscanf(config_record, "%d:%d", cmd, internal_event_num) !=
                    2)
@@ -674,59 +683,27 @@ get_parms(char *config_record,
        if (!tmp)
                goto do_fail;
        tmp++;
-       tmp1 = strchr(tmp, ':');
-       if (!tmp1)
-               goto do_fail;
-
-       count = tmp1 - tmp;
-       *bus_handle = (char *)kmalloc(count + 1, GFP_KERNEL);
-       if (!*bus_handle)
-               goto do_fail;
-       strncpy(*bus_handle, tmp, count);
-       *(*bus_handle + count) = 0;
-
-       tmp = tmp1;
-       tmp++;
-       tmp1 = strchr(tmp, ':');
-       if (!tmp1)
-               goto do_fail;
-       count = tmp1 - tmp;
-       *bus_method = (char *)kmalloc(count + 1, GFP_KERNEL);
-       if (!*bus_method)
-               goto do_fail;
-       strncpy(*bus_method, tmp, count);
-       *(*bus_method + count) = 0;
-
-       tmp = tmp1;
-       tmp++;
-       tmp1 = strchr(tmp, ':');
-       if (!tmp1)
-               goto do_fail;
-       count = tmp1 - tmp;
-       *action_handle = (char *)kmalloc(count + 1, GFP_KERNEL);
-       if (!*action_handle)
-               goto do_fail;
-       strncpy(*action_handle, tmp, count);
-       *(*action_handle + count) = 0;
-
-       tmp = tmp1;
-       tmp++;
-       tmp1 = strchr(tmp, ':');
-       if (!tmp1)
-               goto do_fail;
-       count = tmp1 - tmp;
-       *method = (char *)kmalloc(count + 1, GFP_KERNEL);
-       if (!*method)
-               goto do_fail;
-       strncpy(*method, tmp, count);
-       *(*method + count) = 0;
-
-       if (sscanf(tmp1 + 1, "%d:%d", internal_event_num, external_event_num) <=
-           0)
-               goto do_fail;
-
-       return 6;
-      do_fail:
+       for (i = 0; i < LAST_CONF_ENTRY; i++) {
+               tmp1 = strchr(tmp, ':');
+               if (!tmp1) {
+                       goto do_fail;
+               }
+               count = tmp1 - tmp;
+               config_entry[i] = kzalloc(count + 1, GFP_KERNEL);
+               if (!config_entry[i])
+                       goto handle_failure;
+               strncpy(config_entry[i], tmp, count);
+               tmp = tmp1 + 1;
+       }
+       if (sscanf(tmp, "%d:%d", internal_event_num, external_event_num) <= 0)
+               goto handle_failure;
+       if (!IS_OTHERS(*internal_event_num)) {
+               return 6;
+       }
+handle_failure:
+       while (i-- > 0)
+               kfree(config_entry[i]);
+do_fail:
        return -1;
 }
 
@@ -736,50 +713,34 @@ static ssize_t hotkey_write_config(struct file *file,
                                   size_t count, loff_t * data)
 {
        char *config_record = NULL;
-       char *bus_handle = NULL;
-       char *bus_method = NULL;
-       char *action_handle = NULL;
-       char *method = NULL;
+       char *config_entry[LAST_CONF_ENTRY];
        int cmd, internal_event_num, external_event_num;
        int ret = 0;
-       union acpi_hotkey *key = NULL;
+       union acpi_hotkey *key = kzalloc(sizeof(union acpi_hotkey), GFP_KERNEL);
 
+       if (!key)
+               return -ENOMEM;
 
-       config_record = (char *)kmalloc(count + 1, GFP_KERNEL);
-       if (!config_record)
+       config_record = kzalloc(count + 1, GFP_KERNEL);
+       if (!config_record) {
+               kfree(key);
                return -ENOMEM;
+       }
 
        if (copy_from_user(config_record, buffer, count)) {
                kfree(config_record);
+               kfree(key);
                printk(KERN_ERR PREFIX "Invalid data\n");
                return -EINVAL;
        }
-       config_record[count] = 0;
-
-       ret = get_parms(config_record,
-                       &cmd,
-                       &bus_handle,
-                       &bus_method,
-                       &action_handle,
-                       &method, &internal_event_num, &external_event_num);
-
+       ret = get_parms(config_record, &cmd, config_entry,
+                      &internal_event_num, &external_event_num);
        kfree(config_record);
-       if (IS_OTHERS(internal_event_num))
-               goto do_fail;
        if (ret != 6) {
-             do_fail:
-               kfree(bus_handle);
-               kfree(bus_method);
-               kfree(action_handle);
-               kfree(method);
                printk(KERN_ERR PREFIX "Invalid data format ret=%d\n", ret);
                return -EINVAL;
        }
 
-       key = kmalloc(sizeof(union acpi_hotkey), GFP_KERNEL);
-       if (!key)
-               goto do_fail;
-       memset(key, 0, sizeof(union acpi_hotkey));
        if (cmd == 1) {
                union acpi_hotkey *tmp = NULL;
                tmp = get_hotkey_by_event(&global_hotkey_list,
@@ -791,34 +752,19 @@ static ssize_t hotkey_write_config(struct file *file,
                goto cont_cmd;
        }
        if (IS_EVENT(internal_event_num)) {
-               kfree(bus_method);
-               ret = init_hotkey_device(key, bus_handle, action_handle, method,
-                                        internal_event_num,
-                                        external_event_num);
-       } else
-               ret = init_poll_hotkey_device(key, bus_handle, bus_method,
-                                             action_handle, method,
-                                             internal_event_num);
-       if (ret) {
-               kfree(bus_handle);
-               kfree(action_handle);
-               if (IS_EVENT(internal_event_num))
-                       free_hotkey_buffer(key);
-               else
-                       free_poll_hotkey_buffer(key);
-               kfree(key);
-               printk(KERN_ERR PREFIX "Invalid hotkey\n");
-               return -EINVAL;
+               if (init_hotkey_device(key, config_entry,
+                       internal_event_num, external_event_num))
+                       goto init_hotkey_fail;
+       } else {
+               if (init_poll_hotkey_device(key, config_entry,
+                              internal_event_num))
+                       goto init_poll_hotkey_fail;
        }
-
-      cont_cmd:
-       kfree(bus_handle);
-       kfree(action_handle);
-
+cont_cmd:
        switch (cmd) {
        case 0:
-               if (get_hotkey_by_event
-                   (&global_hotkey_list, key->link.hotkey_standard_num))
+               if (get_hotkey_by_event(&global_hotkey_list,
+                               key->link.hotkey_standard_num))
                        goto fail_out;
                else
                        hotkey_add(key);
@@ -827,6 +773,7 @@ static ssize_t hotkey_write_config(struct file *file,
                hotkey_remove(key);
                break;
        case 2:
+               /* key is kfree()ed if matched*/
                if (hotkey_update(key))
                        goto fail_out;
                break;
@@ -835,11 +782,22 @@ static ssize_t hotkey_write_config(struct file *file,
                break;
        }
        return count;
-      fail_out:
-       if (IS_EVENT(internal_event_num))
-               free_hotkey_buffer(key);
-       else
-               free_poll_hotkey_buffer(key);
+
+init_poll_hotkey_fail:         /* failed init_poll_hotkey_device */
+       kfree(config_entry[bus_method]);
+       config_entry[bus_method] = NULL;
+init_hotkey_fail:              /* failed init_hotkey_device */
+       kfree(config_entry[method]);
+fail_out:
+       kfree(config_entry[bus_handle]);
+       kfree(config_entry[action_handle]);
+       /* No double free since elements =NULL for error cases */
+       if (IS_EVENT(internal_event_num)) {
+               if (config_entry[bus_method])
+                       kfree(config_entry[bus_method]);
+               free_hotkey_buffer(key);        /* frees [method] */
+       } else
+               free_poll_hotkey_buffer(key);  /* frees [bus_method]+[method] */
        kfree(key);
        printk(KERN_ERR PREFIX "invalid key\n");
        return -EINVAL;
@@ -923,10 +881,9 @@ static ssize_t hotkey_execute_aml_method(struct file *file,
        union acpi_hotkey *key;
 
 
-       arg = (char *)kmalloc(count + 1, GFP_KERNEL);
+       arg = kzalloc(count + 1, GFP_KERNEL);
        if (!arg)
                return -ENOMEM;
-       arg[count] = 0;
 
        if (copy_from_user(arg, buffer, count)) {
                kfree(arg);
index 84239d5..6809c28 100644 (file)
@@ -330,7 +330,7 @@ static int acpi_ec_hc_add(struct acpi_device *device)
        status = acpi_evaluate_integer(ec_hc->handle, "_EC", NULL, &val);
        if (ACPI_FAILURE(status)) {
                ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Error obtaining _EC\n"));
-               kfree(ec_hc->smbus);
+               kfree(ec_hc);
                kfree(smbus);
                return -EIO;
        }
index b7d1514..507f051 100644 (file)
@@ -746,6 +746,16 @@ acpi_status acpi_os_wait_semaphore(acpi_handle handle, u32 units, u16 timeout)
        ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Waiting for semaphore[%p|%d|%d]\n",
                          handle, units, timeout));
 
+       /*
+        * This can be called during resume with interrupts off.
+        * Like boot-time, we should be single threaded and will
+        * always get the lock if we try -- timeout or not.
+        * If this doesn't succeed, then we will oops courtesy of
+        * might_sleep() in down().
+        */
+       if (!down_trylock(sem))
+               return AE_OK;
+
        switch (timeout) {
                /*
                 * No Wait:
index db7b350..62bef0b 100644 (file)
@@ -1714,6 +1714,9 @@ static int __init acpi_sbs_init(void)
 {
        int result = 0;
 
+       if (acpi_disabled)
+               return -ENODEV;
+
        init_MUTEX(&sbs_sem);
 
        if (capacity_mode != DEF_CAPACITY_UNIT
index 5fcb50c..698a154 100644 (file)
@@ -4,6 +4,7 @@
 
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/kernel.h>
 #include <linux/acpi.h>
 
 #include <acpi/acpi_drivers.h>
@@ -113,6 +114,8 @@ static struct kset acpi_namespace_kset = {
 static void acpi_device_register(struct acpi_device *device,
                                 struct acpi_device *parent)
 {
+       int err;
+
        /*
         * Linkage
         * -------
@@ -138,7 +141,10 @@ static void acpi_device_register(struct acpi_device *device,
                device->kobj.parent = &parent->kobj;
        device->kobj.ktype = &ktype_acpi_ns;
        device->kobj.kset = &acpi_namespace_kset;
-       kobject_register(&device->kobj);
+       err = kobject_register(&device->kobj);
+       if (err < 0)
+               printk(KERN_WARNING "%s: kobject_register error: %d\n",
+                       __FUNCTION__, err);
        create_sysfs_device_files(device);
 }
 
@@ -1450,7 +1456,9 @@ static int __init acpi_scan_init(void)
        if (acpi_disabled)
                return 0;
 
-       kset_register(&acpi_namespace_kset);
+       result = kset_register(&acpi_namespace_kset);
+       if (result < 0)
+               printk(KERN_ERR PREFIX "kset_register error: %d\n", result);
 
        result = bus_register(&acpi_bus_type);
        if (result) {
index f48227f..d0d84c4 100644 (file)
@@ -262,7 +262,7 @@ acpi_evaluate_integer(acpi_handle handle,
        if (!data)
                return AE_BAD_PARAMETER;
 
-       element = kmalloc(sizeof(union acpi_object), GFP_KERNEL);
+       element = kmalloc(sizeof(union acpi_object), irqs_disabled() ? GFP_ATOMIC: GFP_KERNEL);
        if (!element)
                return AE_NO_MEMORY;
 
index 3c148ea..8a60f39 100644 (file)
@@ -76,7 +76,7 @@ config HOTPLUG_PCI_IBM
 
 config HOTPLUG_PCI_ACPI
        tristate "ACPI PCI Hotplug driver"
-       depends on ACPI_DOCK && HOTPLUG_PCI
+       depends on (!ACPI_DOCK && ACPI && HOTPLUG_PCI) || (ACPI_DOCK && HOTPLUG_PCI)
        help
          Say Y here if you have a system that supports PCI Hotplug using
          ACPI.
index fb08bc9..04618d4 100644 (file)
@@ -1518,6 +1518,63 @@ static void __devinit quirk_netmos(struct pci_dev *dev)
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NETMOS, PCI_ANY_ID, quirk_netmos);
 
+static void __devinit quirk_e100_interrupt(struct pci_dev *dev)
+{
+       u16 command;
+       u32 bar;
+       u8 __iomem *csr;
+       u8 cmd_hi;
+
+       switch (dev->device) {
+       /* PCI IDs taken from drivers/net/e100.c */
+       case 0x1029:
+       case 0x1030 ... 0x1034:
+       case 0x1038 ... 0x103E:
+       case 0x1050 ... 0x1057:
+       case 0x1059:
+       case 0x1064 ... 0x106B:
+       case 0x1091 ... 0x1095:
+       case 0x1209:
+       case 0x1229:
+       case 0x2449:
+       case 0x2459:
+       case 0x245D:
+       case 0x27DC:
+               break;
+       default:
+               return;
+       }
+
+       /*
+        * Some firmware hands off the e100 with interrupts enabled,
+        * which can cause a flood of interrupts if packets are
+        * received before the driver attaches to the device.  So
+        * disable all e100 interrupts here.  The driver will
+        * re-enable them when it's ready.
+        */
+       pci_read_config_word(dev, PCI_COMMAND, &command);
+       pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &bar);
+
+       if (!(command & PCI_COMMAND_MEMORY) || !bar)
+               return;
+
+       csr = ioremap(bar, 8);
+       if (!csr) {
+               printk(KERN_WARNING "PCI: Can't map %s e100 registers\n",
+                       pci_name(dev));
+               return;
+       }
+
+       cmd_hi = readb(csr + 3);
+       if (cmd_hi == 0) {
+               printk(KERN_WARNING "PCI: Firmware left %s e100 interrupts "
+                       "enabled, disabling\n", pci_name(dev));
+               writeb(1, csr + 3);
+       }
+
+       iounmap(csr);
+}
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, quirk_e100_interrupt);
 
 static void __devinit fixup_rev1_53c810(struct pci_dev* dev)
 {