aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firewire/fw-cdev.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/firewire/fw-cdev.c')
-rw-r--r--drivers/firewire/fw-cdev.c23
1 files changed, 21 insertions, 2 deletions
diff --git a/drivers/firewire/fw-cdev.c b/drivers/firewire/fw-cdev.c
index 4a541921a14a..c639915fc3cb 100644
--- a/drivers/firewire/fw-cdev.c
+++ b/drivers/firewire/fw-cdev.c
@@ -113,6 +113,11 @@ static int fw_device_op_open(struct inode *inode, struct file *file)
113 if (device == NULL) 113 if (device == NULL)
114 return -ENODEV; 114 return -ENODEV;
115 115
116 if (fw_device_is_shutdown(device)) {
117 fw_device_put(device);
118 return -ENODEV;
119 }
120
116 client = kzalloc(sizeof(*client), GFP_KERNEL); 121 client = kzalloc(sizeof(*client), GFP_KERNEL);
117 if (client == NULL) { 122 if (client == NULL) {
118 fw_device_put(device); 123 fw_device_put(device);
@@ -200,6 +205,7 @@ fw_device_op_read(struct file *file,
200 return dequeue_event(client, buffer, count); 205 return dequeue_event(client, buffer, count);
201} 206}
202 207
208/* caller must hold card->lock so that node pointers can be dereferenced here */
203static void 209static void
204fill_bus_reset_event(struct fw_cdev_event_bus_reset *event, 210fill_bus_reset_event(struct fw_cdev_event_bus_reset *event,
205 struct client *client) 211 struct client *client)
@@ -209,7 +215,6 @@ fill_bus_reset_event(struct fw_cdev_event_bus_reset *event,
209 event->closure = client->bus_reset_closure; 215 event->closure = client->bus_reset_closure;
210 event->type = FW_CDEV_EVENT_BUS_RESET; 216 event->type = FW_CDEV_EVENT_BUS_RESET;
211 event->generation = client->device->generation; 217 event->generation = client->device->generation;
212 smp_rmb(); /* node_id must not be older than generation */
213 event->node_id = client->device->node_id; 218 event->node_id = client->device->node_id;
214 event->local_node_id = card->local_node->node_id; 219 event->local_node_id = card->local_node->node_id;
215 event->bm_node_id = 0; /* FIXME: We don't track the BM. */ 220 event->bm_node_id = 0; /* FIXME: We don't track the BM. */
@@ -269,6 +274,7 @@ static int ioctl_get_info(struct client *client, void *buffer)
269{ 274{
270 struct fw_cdev_get_info *get_info = buffer; 275 struct fw_cdev_get_info *get_info = buffer;
271 struct fw_cdev_event_bus_reset bus_reset; 276 struct fw_cdev_event_bus_reset bus_reset;
277 struct fw_card *card = client->device->card;
272 unsigned long ret = 0; 278 unsigned long ret = 0;
273 279
274 client->version = get_info->version; 280 client->version = get_info->version;
@@ -294,13 +300,17 @@ static int ioctl_get_info(struct client *client, void *buffer)
294 client->bus_reset_closure = get_info->bus_reset_closure; 300 client->bus_reset_closure = get_info->bus_reset_closure;
295 if (get_info->bus_reset != 0) { 301 if (get_info->bus_reset != 0) {
296 void __user *uptr = u64_to_uptr(get_info->bus_reset); 302 void __user *uptr = u64_to_uptr(get_info->bus_reset);
303 unsigned long flags;
297 304
305 spin_lock_irqsave(&card->lock, flags);
298 fill_bus_reset_event(&bus_reset, client); 306 fill_bus_reset_event(&bus_reset, client);
307 spin_unlock_irqrestore(&card->lock, flags);
308
299 if (copy_to_user(uptr, &bus_reset, sizeof(bus_reset))) 309 if (copy_to_user(uptr, &bus_reset, sizeof(bus_reset)))
300 return -EFAULT; 310 return -EFAULT;
301 } 311 }
302 312
303 get_info->card = client->device->card->index; 313 get_info->card = card->index;
304 314
305 return 0; 315 return 0;
306} 316}
@@ -901,6 +911,9 @@ fw_device_op_ioctl(struct file *file,
901{ 911{
902 struct client *client = file->private_data; 912 struct client *client = file->private_data;
903 913
914 if (fw_device_is_shutdown(client->device))
915 return -ENODEV;
916
904 return dispatch_ioctl(client, cmd, (void __user *) arg); 917 return dispatch_ioctl(client, cmd, (void __user *) arg);
905} 918}
906 919
@@ -911,6 +924,9 @@ fw_device_op_compat_ioctl(struct file *file,
911{ 924{
912 struct client *client = file->private_data; 925 struct client *client = file->private_data;
913 926
927 if (fw_device_is_shutdown(client->device))
928 return -ENODEV;
929
914 return dispatch_ioctl(client, cmd, compat_ptr(arg)); 930 return dispatch_ioctl(client, cmd, compat_ptr(arg));
915} 931}
916#endif 932#endif
@@ -922,6 +938,9 @@ static int fw_device_op_mmap(struct file *file, struct vm_area_struct *vma)
922 unsigned long size; 938 unsigned long size;
923 int page_count, retval; 939 int page_count, retval;
924 940
941 if (fw_device_is_shutdown(client->device))
942 return -ENODEV;
943
925 /* FIXME: We could support multiple buffers, but we don't. */ 944 /* FIXME: We could support multiple buffers, but we don't. */
926 if (client->buffer.pages != NULL) 945 if (client->buffer.pages != NULL)
927 return -EBUSY; 946 return -EBUSY;