#include "surface_hid_core.h"
 
 
+/* -- Utility functions. ---------------------------------------------------- */
+
+static bool surface_hid_is_hot_removed(struct surface_hid_device *shid)
+{
+       /*
+        * Non-ssam client devices, i.e. platform client devices, cannot be
+        * hot-removed.
+        */
+       if (!is_ssam_device(shid->dev))
+               return false;
+
+       return ssam_device_is_hot_removed(to_ssam_device(shid->dev));
+}
+
+
 /* -- Device descriptor access. --------------------------------------------- */
 
 static int surface_hid_load_hid_descriptor(struct surface_hid_device *shid)
 {
        int status;
 
+       if (surface_hid_is_hot_removed(shid))
+               return -ENODEV;
+
        status = shid->ops.get_descriptor(shid, SURFACE_HID_DESC_HID,
                        (u8 *)&shid->hid_desc, sizeof(shid->hid_desc));
        if (status)
 {
        int status;
 
+       if (surface_hid_is_hot_removed(shid))
+               return -ENODEV;
+
        status = shid->ops.get_descriptor(shid, SURFACE_HID_DESC_ATTRS,
                        (u8 *)&shid->attrs, sizeof(shid->attrs));
        if (status)
 static void surface_hid_stop(struct hid_device *hid)
 {
        struct surface_hid_device *shid = hid->driver_data;
+       bool hot_removed;
+
+       /*
+        * Communication may fail for devices that have been hot-removed. This
+        * also includes unregistration of HID events, so we need to check this
+        * here. Only if the device has not been marked as hot-removed, we can
+        * safely disable events.
+        */
+       hot_removed = surface_hid_is_hot_removed(shid);
 
        /* Note: This call will log errors for us, so ignore them here. */
-       ssam_notifier_unregister(shid->ctrl, &shid->notif);
+       __ssam_notifier_unregister(shid->ctrl, &shid->notif, !hot_removed);
 }
 
 static int surface_hid_open(struct hid_device *hid)
        u8 *buf;
        int status;
 
+       if (surface_hid_is_hot_removed(shid))
+               return -ENODEV;
+
        buf = kzalloc(len, GFP_KERNEL);
        if (!buf)
                return -ENOMEM;
 {
        struct surface_hid_device *shid = hid->driver_data;
 
+       if (surface_hid_is_hot_removed(shid))
+               return -ENODEV;
+
        if (rtype == HID_OUTPUT_REPORT && reqtype == HID_REQ_SET_REPORT)
                return shid->ops.output_report(shid, reportnum, buf, len);