Merge branch 'core-rcu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[pandora-kernel.git] / drivers / firewire / core-cdev.c
index b1c1177..e6ad3bb 100644 (file)
@@ -253,14 +253,11 @@ static int fw_device_op_open(struct inode *inode, struct file *file)
        init_waitqueue_head(&client->wait);
        init_waitqueue_head(&client->tx_flush_wait);
        INIT_LIST_HEAD(&client->phy_receiver_link);
+       INIT_LIST_HEAD(&client->link);
        kref_init(&client->kref);
 
        file->private_data = client;
 
-       mutex_lock(&device->client_list_mutex);
-       list_add_tail(&client->link, &device->client_list);
-       mutex_unlock(&device->client_list_mutex);
-
        return nonseekable_open(inode, file);
 }
 
@@ -451,15 +448,20 @@ static int ioctl_get_info(struct client *client, union ioctl_arg *arg)
        if (ret != 0)
                return -EFAULT;
 
+       mutex_lock(&client->device->client_list_mutex);
+
        client->bus_reset_closure = a->bus_reset_closure;
        if (a->bus_reset != 0) {
                fill_bus_reset_event(&bus_reset, client);
-               if (copy_to_user(u64_to_uptr(a->bus_reset),
-                                &bus_reset, sizeof(bus_reset)))
-                       return -EFAULT;
+               ret = copy_to_user(u64_to_uptr(a->bus_reset),
+                                  &bus_reset, sizeof(bus_reset));
        }
+       if (ret == 0 && list_empty(&client->link))
+               list_add_tail(&client->link, &client->device->client_list);
 
-       return 0;
+       mutex_unlock(&client->device->client_list_mutex);
+
+       return ret ? -EFAULT : 0;
 }
 
 static int add_client_resource(struct client *client,
@@ -1583,7 +1585,7 @@ static int dispatch_ioctl(struct client *client,
        if (_IOC_TYPE(cmd) != '#' ||
            _IOC_NR(cmd) >= ARRAY_SIZE(ioctl_handlers) ||
            _IOC_SIZE(cmd) > sizeof(buffer))
-               return -EINVAL;
+               return -ENOTTY;
 
        if (_IOC_DIR(cmd) == _IOC_READ)
                memset(&buffer, 0, _IOC_SIZE(cmd));