static u32 hotkey_orig_mask;
 static u32 hotkey_all_mask;
 static u32 hotkey_reserved_mask;
+static u32 hotkey_mask;
 
 static u16 *hotkey_keycode_map;
 
        return 0;
 }
 
+/*
+ * Call with hotkey_mutex held
+ */
+static int hotkey_mask_get(void)
+{
+       if (tp_features.hotkey_mask) {
+               if (!acpi_evalf(hkey_handle, &hotkey_mask, "DHKN", "d"))
+                       return -EIO;
+       }
+
+       return 0;
+}
+
+/*
+ * Call with hotkey_mutex held
+ */
+static int hotkey_mask_set(u32 mask)
+{
+       int i;
+       int rc = 0;
+
+       if (tp_features.hotkey_mask) {
+               for (i = 0; i < 32; i++) {
+                       u32 m = 1 << i;
+                       if (!acpi_evalf(hkey_handle,
+                                       NULL, "MHKM", "vdd", i + 1,
+                                       !!(mask & m))) {
+                               rc = -EIO;
+                               break;
+                       } else {
+                               hotkey_mask = (hotkey_mask & ~m) | (mask & m);
+                       }
+               }
+
+               /* hotkey_mask_get must be called unconditionally below */
+               if (!hotkey_mask_get() && !rc && hotkey_mask != mask) {
+                       printk(IBM_NOTICE
+                              "requested hot key mask 0x%08x, but "
+                              "firmware forced it to 0x%08x\n",
+                              mask, hotkey_mask);
+               }
+       }
+
+       return rc;
+}
+
+static int hotkey_status_get(int *status)
+{
+       if (!acpi_evalf(hkey_handle, status, "DHKC", "d"))
+               return -EIO;
+
+       return 0;
+}
+
+static int hotkey_status_set(int status)
+{
+       if (!acpi_evalf(hkey_handle, NULL, "MHKC", "vd", status))
+               return -EIO;
+
+       return 0;
+}
+
 /* sysfs hotkey enable ------------------------------------------------- */
 static ssize_t hotkey_enable_show(struct device *dev,
                           struct device_attribute *attr,
                           char *buf)
 {
        int res, status;
-       u32 mask;
 
-       res = hotkey_get(&status, &mask);
+       res = hotkey_status_get(&status);
        if (res)
                return res;
 
                            const char *buf, size_t count)
 {
        unsigned long t;
-       int res, status;
-       u32 mask;
+       int res;
 
        if (parse_strtoul(buf, 1, &t))
                return -EINVAL;
 
-       res = hotkey_get(&status, &mask);
-       if (!res)
-               res = hotkey_set(t, mask);
+       res = hotkey_status_set(t);
 
        return (res) ? res : count;
 }
                           struct device_attribute *attr,
                           char *buf)
 {
-       int res, status;
-       u32 mask;
+       int res;
 
-       res = hotkey_get(&status, &mask);
-       if (res)
-               return res;
+       if (mutex_lock_interruptible(&hotkey_mutex))
+               return -ERESTARTSYS;
+       res = hotkey_mask_get();
+       mutex_unlock(&hotkey_mutex);
 
-       return snprintf(buf, PAGE_SIZE, "0x%08x\n", mask);
+       return (res)?
+               res : snprintf(buf, PAGE_SIZE, "0x%08x\n", hotkey_mask);
 }
 
 static ssize_t hotkey_mask_store(struct device *dev,
                            const char *buf, size_t count)
 {
        unsigned long t;
-       int res, status;
-       u32 mask;
+       int res;
 
        if (parse_strtoul(buf, 0xffffffffUL, &t))
                return -EINVAL;
 
-       res = hotkey_get(&status, &mask);
-       if (!res)
-               hotkey_set(status, t);
+       if (mutex_lock_interruptible(&hotkey_mutex))
+               return -ERESTARTSYS;
+
+       res = hotkey_mask_set(t);
+       mutex_unlock(&hotkey_mutex);
 
        return (res) ? res : count;
 }
                        }
                }
 
-               res = hotkey_get(&hotkey_orig_status, &hotkey_orig_mask);
+               res = hotkey_status_get(&hotkey_orig_status);
                if (!res && tp_features.hotkey_mask) {
-                       res = add_many_to_attr_set(hotkey_dev_attributes,
-                               hotkey_mask_attributes,
-                               ARRAY_SIZE(hotkey_mask_attributes));
+                       res = hotkey_mask_get();
+                       hotkey_orig_mask = hotkey_mask;
+                       if (!res) {
+                               res = add_many_to_attr_set(
+                                       hotkey_dev_attributes,
+                                       hotkey_mask_attributes,
+                                       ARRAY_SIZE(hotkey_mask_attributes));
+                       }
                }
 
                /* Not all thinkpads have a hardware radio switch */
 
                dbg_printk(TPACPI_DBG_INIT,
                                "enabling hot key handling\n");
-               res = hotkey_set(1, (hotkey_all_mask & ~hotkey_reserved_mask)
+               res = hotkey_status_set(1);
+               if (res)
+                       return res;
+               res = hotkey_mask_set((hotkey_all_mask & ~hotkey_reserved_mask)
                                        | hotkey_orig_mask);
                if (res)
                        return res;
 
 static void hotkey_exit(void)
 {
-       int res;
-
        if (tp_features.hotkey) {
-               dbg_printk(TPACPI_DBG_EXIT, "restoring original hotkey mask\n");
-               res = hotkey_set(hotkey_orig_status, hotkey_orig_mask);
-               if (res)
-                       printk(IBM_ERR "failed to restore hotkey to BIOS defaults\n");
+               dbg_printk(TPACPI_DBG_EXIT, "restoring original hot key mask\n");
+               /* no short-circuit boolean operator below! */
+               if ((hotkey_mask_set(hotkey_orig_mask) |
+                    hotkey_status_set(hotkey_orig_status)) != 0)
+                       printk(IBM_ERR "failed to restore hot key mask to BIOS defaults\n");
        }
 
        if (hotkey_dev_attributes) {
 
 static void hotkey_resume(void)
 {
+       if (hotkey_mask_get())
+               printk(IBM_ERR "error while trying to read hot key mask from firmware\n");
        tpacpi_input_send_radiosw();
 }
 
-/*
- * Call with hotkey_mutex held
- */
-static int hotkey_get(int *status, u32 *mask)
-{
-       if (!acpi_evalf(hkey_handle, status, "DHKC", "d"))
-               return -EIO;
-
-       if (tp_features.hotkey_mask)
-               if (!acpi_evalf(hkey_handle, mask, "DHKN", "d"))
-                       return -EIO;
-
-       return 0;
-}
-
-/*
- * Call with hotkey_mutex held
- */
-static int hotkey_set(int status, u32 mask)
-{
-       int i;
-
-       if (!acpi_evalf(hkey_handle, NULL, "MHKC", "vd", status))
-               return -EIO;
-
-       if (tp_features.hotkey_mask)
-               for (i = 0; i < 32; i++) {
-                       int bit = ((1 << i) & mask) != 0;
-                       if (!acpi_evalf(hkey_handle,
-                                       NULL, "MHKM", "vdd", i + 1, bit))
-                               return -EIO;
-               }
-
-       return 0;
-}
-
 /* procfs -------------------------------------------------------------- */
 static int hotkey_read(char *p)
 {
        int res, status;
-       u32 mask;
        int len = 0;
 
        if (!tp_features.hotkey) {
 
        if (mutex_lock_interruptible(&hotkey_mutex))
                return -ERESTARTSYS;
-       res = hotkey_get(&status, &mask);
+       res = hotkey_status_get(&status);
+       if (!res)
+               res = hotkey_mask_get();
        mutex_unlock(&hotkey_mutex);
        if (res)
                return res;
 
        len += sprintf(p + len, "status:\t\t%s\n", enabled(status, 0));
        if (tp_features.hotkey_mask) {
-               len += sprintf(p + len, "mask:\t\t0x%08x\n", mask);
+               len += sprintf(p + len, "mask:\t\t0x%08x\n", hotkey_mask);
                len += sprintf(p + len,
                               "commands:\tenable, disable, reset, <mask>\n");
        } else {
        int res, status;
        u32 mask;
        char *cmd;
-       int do_cmd = 0;
 
        if (!tp_features.hotkey)
                return -ENODEV;
        if (mutex_lock_interruptible(&hotkey_mutex))
                return -ERESTARTSYS;
 
-       res = hotkey_get(&status, &mask);
-       if (res)
-               goto errexit;
+       status = -1;
+       mask = hotkey_mask;
 
        res = 0;
        while ((cmd = next_cmd(&buf))) {
                        res = -EINVAL;
                        goto errexit;
                }
-               do_cmd = 1;
        }
+       if (status != -1)
+               res = hotkey_status_set(status);
 
-       if (do_cmd)
-               res = hotkey_set(status, mask);
+       if (!res && mask != hotkey_mask)
+               res = hotkey_mask_set(mask);
 
 errexit:
        mutex_unlock(&hotkey_mutex);