|
@@ -49,6 +49,28 @@ static struct kobject *dev_kobj;
|
|
|
struct kobject *sysfs_dev_char_kobj;
|
|
|
struct kobject *sysfs_dev_block_kobj;
|
|
|
|
|
|
+static DEFINE_MUTEX(device_hotplug_lock);
|
|
|
+
|
|
|
+void lock_device_hotplug(void)
|
|
|
+{
|
|
|
+ mutex_lock(&device_hotplug_lock);
|
|
|
+}
|
|
|
+
|
|
|
+void unlock_device_hotplug(void)
|
|
|
+{
|
|
|
+ mutex_unlock(&device_hotplug_lock);
|
|
|
+}
|
|
|
+
|
|
|
+int lock_device_hotplug_sysfs(void)
|
|
|
+{
|
|
|
+ if (mutex_trylock(&device_hotplug_lock))
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ /* Avoid busy looping (5 ms of sleep should do). */
|
|
|
+ msleep(5);
|
|
|
+ return restart_syscall();
|
|
|
+}
|
|
|
+
|
|
|
#ifdef CONFIG_BLOCK
|
|
|
static inline int device_is_not_partition(struct device *dev)
|
|
|
{
|
|
@@ -408,9 +430,9 @@ static ssize_t show_online(struct device *dev, struct device_attribute *attr,
|
|
|
{
|
|
|
bool val;
|
|
|
|
|
|
- lock_device_hotplug();
|
|
|
+ device_lock(dev);
|
|
|
val = !dev->offline;
|
|
|
- unlock_device_hotplug();
|
|
|
+ device_unlock(dev);
|
|
|
return sprintf(buf, "%u\n", val);
|
|
|
}
|
|
|
|
|
@@ -424,7 +446,10 @@ static ssize_t store_online(struct device *dev, struct device_attribute *attr,
|
|
|
if (ret < 0)
|
|
|
return ret;
|
|
|
|
|
|
- lock_device_hotplug();
|
|
|
+ ret = lock_device_hotplug_sysfs();
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+
|
|
|
ret = val ? device_online(dev) : device_offline(dev);
|
|
|
unlock_device_hotplug();
|
|
|
return ret < 0 ? ret : count;
|
|
@@ -1479,18 +1504,6 @@ EXPORT_SYMBOL_GPL(put_device);
|
|
|
EXPORT_SYMBOL_GPL(device_create_file);
|
|
|
EXPORT_SYMBOL_GPL(device_remove_file);
|
|
|
|
|
|
-static DEFINE_MUTEX(device_hotplug_lock);
|
|
|
-
|
|
|
-void lock_device_hotplug(void)
|
|
|
-{
|
|
|
- mutex_lock(&device_hotplug_lock);
|
|
|
-}
|
|
|
-
|
|
|
-void unlock_device_hotplug(void)
|
|
|
-{
|
|
|
- mutex_unlock(&device_hotplug_lock);
|
|
|
-}
|
|
|
-
|
|
|
static int device_check_offline(struct device *dev, void *not_used)
|
|
|
{
|
|
|
int ret;
|