May return -EPERM (write access locked out by module
                parameter) or -EACCES (read-only).
 
+       wakeup_reason:
+               Set to 1 if the system is waking up because the user
+               requested a bay ejection.  Set to 2 if the system is
+               waking up because the user requested the system to
+               undock.  Set to zero for normal wake-ups or wake-ups
+               due to unknown reasons.
+
+       wakeup_hotunplug_complete:
+               Set to 1 if the system was waken up because of an
+               undock or bay ejection request, and that request
+               was sucessfully completed.  At this point, it might
+               be useful to send the system back to sleep, at the
+               user's choice.  Refer to HKEY events 0x4003 and
+               0x3003, below.
+
 input layer notes:
 
 A Hot key is mapped to a single input layer EV_KEY event, possibly
 The above events are not propagated by the driver, except for legacy
 compatibility purposes when hotkey_report_mode is set to 1.
 
+0x2304         System is waking up from suspend to undock
+0x2305         System is waking up from suspend to eject bay
+0x2404         System is waking up from hibernation to undock
+0x2405         System is waking up from hibernation to eject bay
+
+The above events are never propagated by the driver.
+
+0x3003         Bay ejection (see 0x2x05) complete, can sleep again
+0x4003         Undocked (see 0x2x04), can sleep again
 0x5010         Brightness level changed (newer Lenovo BIOSes)
 
 The above events are propagated by the driver.
 
 
 static struct mutex hotkey_mutex;
 
+static enum {  /* Reasons for waking up */
+       TP_ACPI_WAKEUP_NONE = 0,        /* None or unknown */
+       TP_ACPI_WAKEUP_BAYEJ,           /* Bay ejection request */
+       TP_ACPI_WAKEUP_UNDOCK,          /* Undock request */
+} hotkey_wakeup_reason;
+
+static int hotkey_autosleep_ack;
+
 static int hotkey_orig_status;
 static u32 hotkey_orig_mask;
 static u32 hotkey_all_mask;
 static struct device_attribute dev_attr_hotkey_report_mode =
        __ATTR(hotkey_report_mode, S_IRUGO, hotkey_report_mode_show, NULL);
 
+/* sysfs wakeup reason ------------------------------------------------- */
+static ssize_t hotkey_wakeup_reason_show(struct device *dev,
+                          struct device_attribute *attr,
+                          char *buf)
+{
+       return snprintf(buf, PAGE_SIZE, "%d\n", hotkey_wakeup_reason);
+}
+
+static struct device_attribute dev_attr_hotkey_wakeup_reason =
+       __ATTR(wakeup_reason, S_IRUGO, hotkey_wakeup_reason_show, NULL);
+
+/* sysfs wakeup hotunplug_complete ------------------------------------- */
+static ssize_t hotkey_wakeup_hotunplug_complete_show(struct device *dev,
+                          struct device_attribute *attr,
+                          char *buf)
+{
+       return snprintf(buf, PAGE_SIZE, "%d\n", hotkey_autosleep_ack);
+}
+
+static struct device_attribute dev_attr_hotkey_wakeup_hotunplug_complete =
+       __ATTR(wakeup_hotunplug_complete, S_IRUGO,
+              hotkey_wakeup_hotunplug_complete_show, NULL);
+
 /* --------------------------------------------------------------------- */
 
 static struct attribute *hotkey_attributes[] __initdata = {
        &dev_attr_hotkey_all_mask.attr,
        &dev_attr_hotkey_recommended_mask.attr,
 #endif
+       &dev_attr_hotkey_wakeup_reason.attr,
+       &dev_attr_hotkey_wakeup_hotunplug_complete.attr,
 };
 
 static int __init hotkey_init(struct ibm_init_struct *iibm)
                str_supported(tp_features.hotkey));
 
        if (tp_features.hotkey) {
-               hotkey_dev_attributes = create_attr_set(10, NULL);
+               hotkey_dev_attributes = create_attr_set(12, NULL);
                if (!hotkey_dev_attributes)
                        return -ENOMEM;
                res = add_many_to_attr_set(hotkey_dev_attributes,
                                unk_ev = 1;
                        }
                        break;
+               case 2:
+                       /* Wakeup reason */
+                       switch (hkey) {
+                       case 0x2304: /* suspend, undock */
+                       case 0x2404: /* hibernation, undock */
+                               hotkey_wakeup_reason = TP_ACPI_WAKEUP_UNDOCK;
+                               ignore_acpi_ev = 1;
+                               break;
+                       case 0x2305: /* suspend, bay eject */
+                       case 0x2405: /* hibernation, bay eject */
+                               hotkey_wakeup_reason = TP_ACPI_WAKEUP_BAYEJ;
+                               ignore_acpi_ev = 1;
+                               break;
+                       default:
+                               unk_ev = 1;
+                       }
+                       if (hotkey_wakeup_reason != TP_ACPI_WAKEUP_NONE) {
+                               printk(TPACPI_INFO
+                                      "woke up due to a hot-unplug "
+                                      "request...\n");
+                       }
+                       break;
+               case 3:
+                       /* bay-related wakeups */
+                       if (hkey == 0x3003) {
+                               hotkey_autosleep_ack = 1;
+                               printk(TPACPI_INFO
+                                      "bay ejected\n");
+                       } else {
+                               unk_ev = 1;
+                       }
+                       break;
+               case 4:
+                       /* dock-related wakeups */
+                       if (hkey == 0x4003) {
+                               hotkey_autosleep_ack = 1;
+                               printk(TPACPI_INFO
+                                      "undocked\n");
+                       } else {
+                               unk_ev = 1;
+                       }
+                       break;
                case 5:
                        /* 0x5000-0x5FFF: On screen display helpers */
                        switch (hkey) {
                        }
                        /* fallthrough to default */
                default:
-                       /* case 2: dock-related */
-                       /*      0x2305 - T43 waking up due to bay lever
-                        *               eject while aslept */
-                       /* case 3: ultra-bay related. maybe bay in dock? */
-                       /*      0x3003 - T43 after wake up by bay lever
-                        *               eject (0x2305) */
                        unk_ev = 1;
                }
                if (unk_ev) {
        }
 }
 
+static void hotkey_suspend(pm_message_t state)
+{
+       /* Do these on suspend, we get the events on early resume! */
+       hotkey_wakeup_reason = TP_ACPI_WAKEUP_NONE;
+       hotkey_autosleep_ack = 0;
+}
+
 static void hotkey_resume(void)
 {
        if (hotkey_mask_get())
        .write = hotkey_write,
        .exit = hotkey_exit,
        .resume = hotkey_resume,
+       .suspend = hotkey_suspend,
        .acpi = &ibm_hotkey_acpidriver,
 };